Bird
Raised Fist0
Typescriptprogramming~15 mins

Declaring functions and classes in Typescript - Deep Dive

Choose your learning style10 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.

Practice

(1/5)
1. What is the main purpose of a function in TypeScript?
easy
A. To create a new type of variable
B. To store data without any behavior
C. To perform a specific task and optionally return a result
D. To define a constant value

Solution

  1. Step 1: Understand what a function does

    A function is a block of code designed to perform a specific task.
  2. Step 2: Recognize the role of return values

    Functions can return results after performing their task, making them reusable.
  3. Final Answer:

    To perform a specific task and optionally return a result -> Option C
  4. Quick Check:

    Function purpose = perform task + return result [OK]
Hint: Functions do tasks and can give back results [OK]
Common Mistakes:
  • Confusing functions with variables
  • Thinking functions only store data
  • Believing functions cannot return values
2. Which of the following is the correct way to declare a function named greet that takes a string name and returns a string in TypeScript?
easy
A. function greet(name: string): string { return `Hello, ${name}`; }
B. function greet(name) { return 'Hello, ' + name; }
C. function greet(name: string) { console.log('Hello, ' + name); }
D. function greet(): string { return name; }

Solution

  1. Step 1: Check function parameter and return types

    function greet(name: string): string { return `Hello, ${name}`; } correctly declares the parameter name as a string and the return type as string.
  2. Step 2: Verify function body returns a string

    function greet(name: string): string { return `Hello, ${name}`; } returns a template string greeting the name, matching the return type.
  3. Final Answer:

    function greet(name: string): string { return `Hello, ${name}`; } -> Option A
  4. Quick Check:

    Correct parameter and return types = function greet(name: string): string { return `Hello, ${name}`; } [OK]
Hint: Specify parameter and return types explicitly [OK]
Common Mistakes:
  • Omitting parameter types in TypeScript
  • Not returning a value when return type is declared
  • Using console.log instead of return
3. What will be the output of the following TypeScript code?
class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  greet() {
    return `Hi, I am ${this.name}`;
  }
}
const p = new Person('Anna');
console.log(p.greet());
medium
A. Hi, I am Anna
B. Hi, I am undefined
C. Error: Property 'name' does not exist
D. Hi, I am

Solution

  1. Step 1: Understand class construction

    The Person class sets this.name to the passed argument 'Anna' in the constructor.
  2. Step 2: Analyze the greet method output

    The greet method returns a string including this.name, which is 'Anna'.
  3. Final Answer:

    Hi, I am Anna -> Option A
  4. Quick Check:

    Class property set correctly = 'Hi, I am Anna' [OK]
Hint: Constructor sets properties; methods use them [OK]
Common Mistakes:
  • Forgetting to assign constructor parameter to this.name
  • Expecting undefined because of missing this
  • Confusing method return with console.log output
4. Identify the error in this TypeScript class declaration:
class Car {
  model: string;
  constructor(model) {
    this.model = model;
  }
  display() {
    console.log('Model: ' + this.model);
  }
}
medium
A. Property 'model' should be private
B. Missing return type for display method
C. Constructor should not have parameters
D. Missing type annotation for constructor parameter 'model'

Solution

  1. Step 1: Check constructor parameter types

    In TypeScript, constructor parameters should have type annotations; here, model lacks a type.
  2. Step 2: Verify other parts

    The display method does not require a return type annotation since it returns void implicitly.
  3. Final Answer:

    Missing type annotation for constructor parameter 'model' -> Option D
  4. Quick Check:

    Constructor parameters need types = Missing type annotation for constructor parameter 'model' [OK]
Hint: Always type constructor parameters in TypeScript [OK]
Common Mistakes:
  • Omitting parameter types in constructors
  • Thinking methods must always declare return types
  • Assuming properties must be private by default
5. You want to create a TypeScript class Calculator with a method add that takes two numbers and returns their sum. Which code correctly implements this with proper types and usage?
hard
A. class Calculator { add(a, b) { return a + b; } } const calc = Calculator(); console.log(calc.add(5, 3));
B. class Calculator { add(a: number, b: number): number { return a + b; } } const calc = new Calculator(); console.log(calc.add(5, 3));
C. class Calculator { add(a: number, b: number) { console.log(a + b); } } const calc = new Calculator(); calc.add(5, 3);
D. class Calculator { add(a: number, b: number): number { return a + b; } } const calc = new Calculator(); console.log(calc.add('5', '3'));

Solution

  1. Step 1: Check method declaration and types

    class Calculator { add(a: number, b: number): number { return a + b; } } const calc = new Calculator(); console.log(calc.add(5, 3)); declares add with parameters typed as numbers and return type number, which is correct.
  2. Step 2: Verify object creation and method call

    class Calculator { add(a: number, b: number): number { return a + b; } } const calc = new Calculator(); console.log(calc.add(5, 3)); creates an instance with new Calculator() and calls add(5, 3), which returns 8.
  3. Final Answer:

    Correct class with typed method and proper usage -> Option B
  4. Quick Check:

    Typed method + new instance + correct call = class Calculator { add(a: number, b: number): number { return a + b; } } const calc = new Calculator(); console.log(calc.add(5, 3)); [OK]
Hint: Use 'new' to create class instances and type parameters [OK]
Common Mistakes:
  • Calling class without 'new'
  • Omitting parameter types
  • Passing wrong argument types (like strings instead of numbers)
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard