Functions are fundamental in TypeScript. Learn how to type them properly.
Function Declarations
Basic Function
function greet(name: string): string {
return `Hello, ${name}!`;
}
Function Parameters
// Required parameters
function add(a: number, b: number): number {
return a + b;
}
// Optional parameters (use ?)
function greet(name: string, title?: string): string {
if (title) {
return `Hello, ${title} ${name}!`;
}
return `Hello, ${name}!`;
}
greet("Alice"); // "Hello, Alice!"
greet("Alice", "Dr."); // "Hello, Dr. Alice!"
Default Parameters
function greet(name: string, greeting: string = "Hello"): string {
return `${greeting}, ${name}!`;
}
greet("Alice"); // "Hello, Alice!"
greet("Alice", "Hi"); // "Hi, Alice!"
Rest Parameters
function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3); // 6
sum(1, 2, 3, 4, 5); // 15
Function Expressions
Named Function Expression
const multiply = function(x: number, y: number): number {
return x * y;
};
Arrow Functions
// Single expression
const add = (a: number, b: number): number => a + b;
// Multiple statements
const greet = (name: string): string => {
const message = `Hello, ${name}!`;
return message;
};
Function Types
Type Annotations for Functions
// Function type
let myFunction: (a: number, b: number) => number;
myFunction = function(x: number, y: number): number {
return x + y;
};
Type Aliases for Functions
type MathOperation = (a: number, b: number) => number;
const add: MathOperation = (a, b) => a + b;
const multiply: MathOperation = (a, b) => a * b;
Function Overloads
Define multiple function signatures for the same function.
// Overload signatures
function process(value: string): string;
function process(value: number): number;
function process(value: boolean): boolean;
// Implementation
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;
}
}
process("hello"); // Returns: "HELLO"
process(5); // Returns: 10
process(true); // Returns: false
Return Types
Explicit Return Types
function getAge(): number {
return 25;
}
function getName(): string {
return "Alice";
}
void Return Type
For functions that don't return a value.
function logMessage(message: string): void {
console.log(message);
// No return statement needed
}
never Return Type
For functions that never return (throw errors or infinite loops).
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {
// Never returns
}
}
this Parameter
Type the this context in functions.
interface User {
name: string;
greet(this: User): void;
}
const user: User = {
name: "Alice",
greet() {
console.log(`Hello, I'm ${this.name}`);
}
};
Generic Functions
Basic introduction (covered in detail in Intermediate level).
function identity<T>(arg: T): T {
return arg;
}
identity<string>("hello"); // string
identity<number>(42); // number
Exercises
Exercise 1: Basic Functions
// Create a function called 'calculateArea' that:
// - Takes width (number) and height (number) as parameters
// - Returns the area (number)
// - Has proper type annotations
Exercise 2: Optional Parameters
// Create a function called 'createUser' that:
// - Takes name (string, required)
// - Takes email (string, optional)
// - Takes age (number, optional)
// - Returns a user object
Exercise 3: Default Parameters
// Create a function called 'createGreeting' that:
// - Takes name (string, required)
// - Takes greeting (string, default: "Hello")
// - Returns a greeting string
Exercise 4: Rest Parameters
// Create a function called 'average' that:
// - Takes any number of numbers as arguments
// - Returns the average (number)
Exercise 5: Function Overloads
// Create overloaded function 'format' that:
// - If given a string, returns it uppercase
// - If given a number, returns it as a string with 2 decimal places
Best Practices
- Always type function parameters - Never use implicit
any - Use explicit return types - Makes intent clear
- Prefer arrow functions - More concise for simple functions
- Use default parameters - Instead of optional parameters when possible
- Document complex functions - Add JSDoc comments
Common Mistakes
- Forgetting return type annotations
// ❌ Bad
function add(a: number, b: number) {
return a + b;
}
// ✅ Good
function add(a: number, b: number): number {
return a + b;
}
- Using
anyfor parameters
// ❌ Bad
function process(data: any) {
// ...
}
// ✅ Good
function process(data: UserData) {
// ...
}
- Not handling optional parameters
// ❌ Bad
function greet(name: string, title?: string): string {
return `Hello, ${title} ${name}!`; // title might be undefined
}
Next Steps
Learn about Interfaces.