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"
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.