TypeScript Function Overloading
Create functions with multiple signatures
🔄 What is Function Overloading?
Function overloading allows you to define multiple function signatures for the same function name. This enables a function to accept different parameter types or counts while maintaining type safety throughout your code.
// Overload signatures
function combine(a: string, b: string): string;
function combine(a: number, b: number): number;
// Implementation
function combine(a: any, b: any): any {
return a + b;
}
console.log(combine("Hello, ", "World!"));
console.log(combine(10, 20));
Output:
Hello, World!
30
Overloading Concepts
Multiple Signatures
Define different parameter types
function format(value: string): string;
function format(value: number): string;
Implementation
Single implementation handles all cases
function format(value: any): string {
return String(value);
}
Type Safety
Compiler checks correct usage
format("text"); // ✓ Valid
format(123); // ✓ Valid
format(true); // ✗ Error
Different Arities
Vary parameter counts
function build(a: string): string;
function build(a: string, b: string): string;
🔹 Basic Overloading Example
Create a function that works with different types:
// Overload signatures
function double(value: number): number;
function double(value: string): string;
// Implementation signature
function double(value: any): any {
if (typeof value === "number") {
return value * 2;
} else {
return value + value;
}
}
console.log(double(5));
console.log(double("Hello"));
Output:
10
HelloHello
🔹 Overloading with Different Parameter Counts
Handle functions with optional parameters:
// Overload signatures
function greet(name: string): string;
function greet(firstName: string, lastName: string): string;
// Implementation
function greet(firstName: string, lastName?: string): string {
if (lastName) {
return `Hello, ${firstName} ${lastName}!`;
}
return `Hello, ${firstName}!`;
}
console.log(greet("Alice"));
console.log(greet("Bob", "Smith"));
Output:
Hello, Alice!
Hello, Bob Smith!
🔹 Overloading with Different Return Types
Return different types based on input:
// Overload signatures
function getValue(key: "name"): string;
function getValue(key: "age"): number;
function getValue(key: "active"): boolean;
// Implementation
function getValue(key: string): string | number | boolean {
const data: any = {
name: "Alice",
age: 30,
active: true
};
return data[key];
}
console.log(getValue("name"));
console.log(getValue("age"));
console.log(getValue("active"));
Output:
Alice
30
true
🔹 Practical Overloading Example
Create a flexible formatting function:
// Overload signatures
function formatDate(date: Date): string;
function formatDate(day: number, month: number, year: number): string;
// Implementation
function formatDate(
dateOrDay: Date | number,
month?: number,
year?: number
): string {
if (dateOrDay instanceof Date) {
return dateOrDay.toLocaleDateString();
} else {
return `${dateOrDay}/${month}/${year}`;
}
}
console.log(formatDate(new Date()));
console.log(formatDate(15, 6, 2024));
Output:
9/30/2025
15/6/2024
🔹 Overloading with Objects
Handle different object structures:
// Overload signatures
function createUser(name: string): { name: string };
function createUser(name: string, age: number): { name: string; age: number };
// Implementation
function createUser(name: string, age?: number): any {
if (age !== undefined) {
return { name, age };
}
return { name };
}
console.log(createUser("Alice"));
console.log(createUser("Bob", 25));
Output:
{ name: 'Alice' }
{ name: 'Bob', age: 25 }
💡 Best Practices:
- List overload signatures from most specific to least specific
- The implementation signature must be compatible with all overloads
- Use overloading when the same operation works with different types
- Keep overloads simple and intuitive for better code readability