Skip to main content

Module 3: Functions in TypeScript

Functions are the building blocks of TypeScript applications. This module covers function types, parameters, return values, and advanced function patterns.


1. Function Type Annotations​

Basic Function​

function greet(name: string): string {
return `Hello, ${name}!`;
}

let result: string = greet("Alice");

Function with Multiple Parameters​

function add(a: number, b: number): number {
return a + b;
}

console.log(add(5, 10)); // 15

Void Return Type​

function logMessage(message: string): void {
console.log(message);
}

2. Optional Parameters​

Use ? to make parameters optional.

function buildName(firstName: string, lastName?: string): string {
if (lastName) {
return `${firstName} ${lastName}`;
}
return firstName;
}

console.log(buildName("John")); // "John"
console.log(buildName("John", "Doe")); // "John Doe"
Parameter Order

Optional parameters must come after required parameters.


3. Default Parameters​

function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}

console.log(greet("Alice")); // "Hello, Alice!"
console.log(greet("Bob", "Hi")); // "Hi, Bob!"

Default Parameters with Type Inference​

function createPoint(x: number = 0, y: number = 0) {
return { x, y };
}

4. Rest Parameters​

Collect multiple arguments into an array.

function sum(...numbers: number[]): number {
return numbers.reduce((total, n) => total + n, 0);
}

console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20, 30, 40)); // 100

5. Function Expressions​

Anonymous Function​

let multiply = function(a: number, b: number): number {
return a * b;
};

Arrow Functions​

let divide = (a: number, b: number): number => {
return a / b;
};

// Concise arrow function
let square = (n: number): number => n * n;

6. Function Types​

Define the type of a function variable.

let mathOperation: (x: number, y: number) => number;

mathOperation = (a, b) => a + b; // ✅ OK
mathOperation = (a, b) => a * b; // ✅ OK
// mathOperation = (a: string) => a; // ❌ Error

Type Alias for Functions​

type MathFunc = (a: number, b: number) => number;

let add: MathFunc = (x, y) => x + y;
let subtract: MathFunc = (x, y) => x - y;

7. Function Overloading​

Define multiple function signatures.

// Overload signatures
function process(value: string): string;
function process(value: number): number;
function process(value: boolean): boolean;

// Implementation signature
function process(value: string | number | boolean): string | number | boolean {
if (typeof value === "string") {
return value.toUpperCase();
} else if (typeof value === "number") {
return value * 2;
} else {
return !value;
}
}

console.log(process("hello")); // "HELLO"
console.log(process(5)); // 10
console.log(process(true)); // false

8. Callback Functions​

function fetchData(callback: (data: string) => void): void {
setTimeout(() => {
callback("Data loaded");
}, 1000);
}

fetchData((data) => {
console.log(data); // "Data loaded"
});

Callback with Error Handling​

type Callback = (error: Error | null, data?: string) => void;

function loadUser(id: number, callback: Callback): void {
if (id > 0) {
callback(null, `User ${id}`);
} else {
callback(new Error("Invalid ID"));
}
}

9. Generic Functions​

Create reusable functions that work with multiple types.

function identity<T>(value: T): T {
return value;
}

let num = identity<number>(42);
let str = identity<string>("Hello");
let auto = identity(100); // Type inferred as number

Generic Array Function​

function getFirst<T>(arr: T[]): T | undefined {
return arr[0];
}

let firstNum = getFirst([1, 2, 3]); // number | undefined
let firstStr = getFirst(["a", "b", "c"]); // string | undefined

10. this in Functions​

Regular Function Context​

let user = {
name: "Alice",
greet: function() {
console.log(`Hello, ${this.name}`);
}
};

user.greet(); // "Hello, Alice"

Arrow Function and this​

let timer = {
seconds: 0,
start: function() {
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
};

timer.start(); // Correctly binds `this`

Explicit this Parameter​

interface User {
name: string;
}

function greet(this: User, greeting: string) {
console.log(`${greeting}, ${this.name}`);
}

let user: User = { name: "Bob" };
greet.call(user, "Hello"); // "Hello, Bob"

Key Takeaways​

✅ Always type function parameters and return values
✅ Use optional and default parameters for flexibility
✅ Rest parameters collect variable arguments
✅ Function overloading provides multiple signatures
✅ Generics make functions reusable across types
✅ Arrow functions inherit this from surrounding scope


Practice Exercises​

Exercise 1: Function with Optional Parameters​

function calculateArea(width: number, height?: number): number {
return height ? width * height : width * width;
}

Exercise 2: Rest Parameters​

function concatenate(...strings: string[]): string {
return strings.join(" ");
}

console.log(concatenate("Hello", "TypeScript", "World"));

Exercise 3: Generic Function​

function reverseArray<T>(arr: T[]): T[] {
return arr.reverse();
}

console.log(reverseArray([1, 2, 3]));
console.log(reverseArray(["a", "b", "c"]));

Next Steps​

In Module 4, we'll explore Interfaces and learn how to define contracts for objects, classes, and functions.