0
0
Typescriptprogramming~15 mins

Declaring functions and classes in Typescript - Deep Dive

Choose your learning style9 modes available
Overview - Declaring functions and classes
What is it?
Declaring functions and classes in TypeScript means creating reusable blocks of code that perform tasks or represent objects with properties and behaviors. Functions are like little machines that take inputs, do something, and give outputs. Classes are blueprints for creating objects that share common features and actions. Together, they help organize code clearly and make programs easier to build and understand.
Why it matters
Without functions and classes, code would be repetitive, messy, and hard to manage. Functions let you reuse code without rewriting it, saving time and reducing mistakes. Classes help model real-world things in code, making complex programs simpler to design and maintain. Without these, building anything beyond tiny scripts would be chaotic and error-prone.
Where it fits
Before learning to declare functions and classes, you should understand basic TypeScript syntax, variables, and data types. After mastering this topic, you can learn about advanced object-oriented programming concepts, interfaces, inheritance, and how to organize large applications using modules.
Mental Model
Core Idea
Functions are reusable actions, and classes are blueprints for creating objects with shared properties and behaviors.
Think of it like...
Think of a function as a kitchen appliance like a blender: you put ingredients in, it processes them, and gives you a smoothie. A class is like a recipe book that tells you how to make different dishes (objects) with similar steps and ingredients.
┌─────────────┐        ┌─────────────┐
│  Function   │        │   Class     │
│  (Action)   │        │ (Blueprint) │
└─────┬───────┘        └─────┬───────┘
      │                      │
      │                      │
      ▼                      ▼
┌─────────────┐        ┌─────────────┐
│  Input(s)   │        │  Properties │
│  Process    │        │  Methods    │
│  Output     │        └─────────────┘
└─────────────┘
Build-Up - 7 Steps
1
FoundationBasic function declaration syntax
🤔
Concept: How to write a simple function that takes inputs and returns output.
In TypeScript, you declare a function using the 'function' keyword, followed by a name, parentheses for parameters, and curly braces for the body. Example: function greet(name: string): string { return `Hello, ${name}!`; } This function takes a string 'name' and returns a greeting message.
Result
You can call greet('Alice') and get 'Hello, Alice!' as output.
Understanding the basic syntax lets you create reusable actions that can take inputs and produce outputs, which is the foundation of programming.
2
FoundationBasic class declaration syntax
🤔
Concept: How to define a class with properties and methods.
A class in TypeScript is declared using the 'class' keyword, followed by a name and curly braces. Inside, you define properties and methods. Example: class Person { name: string; constructor(name: string) { this.name = name; } greet(): string { return `Hi, I'm ${this.name}`; } } This class has a property 'name' and a method 'greet'.
Result
Creating 'new Person("Bob")' gives an object with name 'Bob' and a greet method that returns 'Hi, I'm Bob'.
Knowing how to declare classes lets you model real-world things as objects with shared features and behaviors.
3
IntermediateFunction parameters and return types
🤔Before reading on: do you think TypeScript requires specifying types for function parameters and return values? Commit to yes or no.
Concept: TypeScript allows and encourages specifying types for function inputs and outputs to catch errors early.
You can specify types for each parameter and the return type after the parentheses. Example: function add(a: number, b: number): number { return a + b; } If you try to pass a string instead of a number, TypeScript will warn you before running the code.
Result
Calling add(2, 3) returns 5. Calling add('2', 3) causes a type error during development.
Knowing how to type function parameters and returns helps prevent bugs by catching mistakes before running the program.
4
IntermediateClass constructors and 'this' keyword
🤔Before reading on: do you think 'this' inside a class method refers to the class itself or the object instance? Commit to your answer.
Concept: The constructor initializes new objects, and 'this' refers to the current object instance inside methods.
The constructor is a special method that runs when you create a new object. Inside methods, 'this' accesses the object's own properties. Example: class Car { model: string; constructor(model: string) { this.model = model; } describe(): string { return `This car is a ${this.model}`; } } Here, 'this.model' refers to the model property of the specific car object.
Result
Creating 'new Car("Tesla")' and calling describe() returns 'This car is a Tesla'.
Understanding 'this' is key to working with object properties and methods correctly in classes.
5
IntermediateArrow functions vs regular functions
🤔Before reading on: do arrow functions have their own 'this' or inherit it from the surrounding context? Commit to your answer.
Concept: Arrow functions do not have their own 'this'; they use 'this' from where they are defined.
Regular functions have their own 'this' depending on how they are called. Arrow functions inherit 'this' from the surrounding code. Example: class Counter { count = 0; incrementRegular() { setTimeout(function() { this.count++; console.log(this.count); }, 1000); } incrementArrow() { setTimeout(() => { this.count++; console.log(this.count); }, 1000); } } Calling incrementRegular() logs NaN or error because 'this' is wrong. incrementArrow() works as expected.
Result
Arrow functions help keep the correct 'this' inside callbacks.
Knowing the difference prevents common bugs with 'this' inside asynchronous code.
6
AdvancedClass inheritance and method overriding
🤔Before reading on: do subclasses inherit private properties from parent classes? Commit to yes or no.
Concept: Classes can extend other classes to reuse and customize behavior; private properties are not accessible to subclasses.
You can create a subclass using 'extends' keyword. Subclasses inherit public and protected members but not private ones. They can override methods to change behavior. Example: class Animal { protected name: string; constructor(name: string) { this.name = name; } speak(): string { return `${this.name} makes a sound.`; } } class Dog extends Animal { speak(): string { return `${this.name} barks.`; } } const dog = new Dog('Rex'); console.log(dog.speak()); This prints 'Rex barks.'
Result
Inheritance allows code reuse and customization while controlling access with visibility modifiers.
Understanding inheritance and access control helps design flexible and safe class hierarchies.
7
ExpertFunction overloads and class decorators
🤔Before reading on: do you think TypeScript supports multiple function signatures for the same function? Commit to yes or no.
Concept: TypeScript allows declaring multiple function signatures (overloads) and supports decorators to modify classes or methods at runtime.
Function overloads let you define different ways to call a function with different parameter types: function combine(a: string, b: string): string; function combine(a: number, b: number): number; function combine(a: any, b: any): any { return a + b; } Decorators are special functions that can modify classes or methods. Example: function sealed(constructor: Function) { Object.seal(constructor); Object.seal(constructor.prototype); } @sealed class Example {} This prevents adding new properties to the class or its prototype.
Result
Overloads improve function flexibility; decorators enable powerful meta-programming.
Knowing these advanced features unlocks sophisticated patterns and safer, more expressive code.
Under the Hood
Functions in TypeScript compile down to JavaScript functions, which are objects that can be called with parameters and return values. Classes are syntactic sugar over JavaScript's prototype-based inheritance, creating constructor functions and setting up prototype chains for shared methods. The 'this' keyword inside functions and methods refers to the calling context, which can change depending on how the function is called. TypeScript adds static type checking at compile time but does not change runtime behavior.
Why designed this way?
TypeScript was designed to add type safety and modern features to JavaScript without changing its runtime model. Functions and classes follow JavaScript's flexible but sometimes confusing behavior, so TypeScript adds types and syntax to help developers catch errors early and write clearer code. The class syntax was introduced to make object-oriented programming easier and more familiar to developers from other languages.
┌───────────────┐
│ TypeScript    │
│ Source Code   │
└──────┬────────┘
       │ Compiled to
       ▼
┌───────────────┐
│ JavaScript    │
│ Functions &   │
│ Prototype     │
│ Objects       │
└──────┬────────┘
       │ Runtime
       ▼
┌───────────────┐
│ JavaScript    │
│ Engine (V8,   │
│ SpiderMonkey) │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does 'this' inside a regular function always refer to the object owning the method? Commit yes or no.
Common Belief:Many believe 'this' inside a regular function always points to the object that owns the method.
Tap to reveal reality
Reality:'this' depends on how the function is called, not where it is defined. If called as a standalone function, 'this' can be undefined or the global object.
Why it matters:Misunderstanding 'this' causes bugs where methods lose their context, leading to errors or unexpected behavior.
Quick: Can subclasses access private properties of their parent classes? Commit yes or no.
Common Belief:Some think subclasses can access all properties of their parent classes, including private ones.
Tap to reveal reality
Reality:Private properties are only accessible within the class that declares them, not in subclasses.
Why it matters:Assuming access to private members can cause compilation errors and breaks encapsulation principles.
Quick: Does TypeScript enforce types at runtime? Commit yes or no.
Common Belief:Many believe TypeScript types prevent type errors during program execution.
Tap to reveal reality
Reality:TypeScript types are erased during compilation; they only help during development and do not enforce types at runtime.
Why it matters:Relying on TypeScript types for runtime safety can lead to unexpected runtime errors if JavaScript code violates assumptions.
Quick: Do arrow functions have their own 'this'? Commit yes or no.
Common Belief:Some think arrow functions behave exactly like regular functions regarding 'this'.
Tap to reveal reality
Reality:Arrow functions do not have their own 'this'; they inherit it from the surrounding scope.
Why it matters:Misusing arrow functions can cause 'this' to refer to unexpected objects, breaking code logic.
Expert Zone
1
TypeScript's class syntax compiles to prototype-based JavaScript, so understanding prototypes helps debug complex inheritance issues.
2
Function overloads in TypeScript are only compile-time checks; the implementation must handle all cases manually.
3
Decorators are an experimental feature and require enabling specific compiler options; they can modify class behavior dynamically but may affect performance.
When NOT to use
Avoid using classes when simple data structures or functions suffice, as classes add complexity and overhead. Prefer functional programming patterns or interfaces for lightweight code. Also, avoid decorators in performance-critical code or libraries targeting environments without decorator support.
Production Patterns
In real-world TypeScript projects, functions are often declared as arrow functions for lexical 'this' binding. Classes are used to model domain entities with clear interfaces. Decorators are common in frameworks like Angular for dependency injection and metadata. Function overloads help create flexible APIs with clear type safety.
Connections
Object-oriented programming
Declaring classes in TypeScript builds on core object-oriented principles like encapsulation and inheritance.
Understanding classes in TypeScript deepens knowledge of OOP concepts used across many programming languages.
Functional programming
Functions in TypeScript can be pure and reusable, connecting to functional programming ideas.
Knowing how to declare and use functions well helps bridge imperative and functional programming styles.
Blueprints in architecture
Classes as blueprints relate to how architects design buildings before construction.
Seeing classes as blueprints helps grasp how code models real-world objects and behaviors systematically.
Common Pitfalls
#1Losing 'this' context inside callbacks.
Wrong approach:class Timer { seconds = 0; start() { setInterval(function() { this.seconds++; console.log(this.seconds); }, 1000); } }
Correct approach:class Timer { seconds = 0; start() { setInterval(() => { this.seconds++; console.log(this.seconds); }, 1000); } }
Root cause:Using a regular function inside setInterval creates a new 'this' context, losing the class instance reference.
#2Accessing private properties from subclasses.
Wrong approach:class Parent { private secret = 'hidden'; } class Child extends Parent { reveal() { return this.secret; } }
Correct approach:class Parent { protected secret = 'hidden'; } class Child extends Parent { reveal() { return this.secret; } }
Root cause:Private properties are inaccessible outside their class; using 'protected' allows subclass access.
#3Forgetting to specify function return types.
Wrong approach:function multiply(a: number, b: number) { return a * b; }
Correct approach:function multiply(a: number, b: number): number { return a * b; }
Root cause:Omitting return types can lead to implicit 'any' or incorrect type inference, reducing type safety.
Key Takeaways
Functions are reusable blocks of code that take inputs and produce outputs, essential for organizing logic.
Classes are blueprints for creating objects with shared properties and behaviors, enabling object-oriented design.
TypeScript adds static types to functions and classes, helping catch errors early and improving code clarity.
Understanding 'this' and how it behaves differently in regular and arrow functions is crucial to avoid bugs.
Advanced features like function overloads and decorators provide powerful tools but require careful use and understanding.