What is function overloading (overload)?
What function overloading (overload) is
Function overloading is the ability to describe several signatures (call variants) of the same function with different argument types and return values.
In simpler terms: a single function can behave differently depending on the types of the arguments.
TypeScript lets you type this through several signatures "on top" and a single implementation "below".
Example 1. A simple overload by argument type
// Overloads (call variants)
function reverse(value: string): string;
function reverse(value: number[]): number[];
// Implementation (one for all cases)
function reverse(value: string | number[]): string | number[] {
if (typeof value === "string") {
return value.split("").reverse().join("");
} else {
return value.slice().reverse();
}
}
// Usage examples
const str = reverse("TypeScript"); // string
const arr = reverse([1, 2, 3]); // number[]TypeScript understands that:
- if you pass a
string, the function returnsstring - if you pass
number[], it returnsnumber[]
How it works
TypeScript sees all the signatures but checks them top to bottom. When it finds a matching one, it applies it. The implementation is not visible to the caller; it only serves to run the code.
Example 2. Different return types
function toArray(value: string): string[];
function toArray(value: number): number[];
function toArray(value: string | number): (string | number)[] {
return [value];
}
toArray("hi"); // string[]
toArray(42); // number[]Example 3. A different number of parameters
function createUser(name: string): { name: string };
function createUser(name: string, age: number): { name: string; age: number };
function createUser(name: string, age?: number) {
return age ? { name, age } : { name };
}
createUser("Tim"); // { name: string }
createUser("Tim", 25); // { name: string; age: number }Here two signatures describe which combinations of arguments are allowed, and the implementation combines them in a single body.
Example 4. Overloading in generic functions
function wrap<T>(value: T): { data: T };
function wrap<T>(value: T[]): { data: T[] };
function wrap<T>(value: T | T[]): { data: T | T[] } {
return { data: value };
}
wrap(42); // { data: number }
wrap([1, 2]); // { data: number[] }How to write overloads correctly
Structure:
// 1. First: the overload signatures
function fn(param: Type1): ReturnType1;
function fn(param: Type2): ReturnType2;
// 2. Then: the implementation with union types
function fn(param: Type1 | Type2): ReturnType1 | ReturnType2 {
// logic
}Important: the implementation must always handle all the variants. TypeScript checks that it is compatible with every signature.
Mistakes when overloading incorrectly
You cannot write the implementation before the overload signatures:
function fn(x: any): any { return x; } // Error: the implementation must come last
function fn(x: string): string;
function fn(x: number): number;It must be the other way around:
function fn(x: string): string;
function fn(x: number): number;
function fn(x: any): any { return x; }When to use overloading
Use overloading when:
- the function has different argument types and different results;
- this cannot simply be expressed with a
union; - you need to keep strict typing of the return value.
An alternative to overloading: generics
Sometimes it is simpler to express the same thing through generic types:
function wrap<T>(value: T): { data: T } {
return { data: value };
}Generic functions are more compact and often preferable when the logic is the same for all types.
Summary cheat sheet
| Feature | Function overloading |
|---|---|
| Number of implementations | Always one |
| Number of signatures | Several, on top |
| Different arguments | Yes |
| Different return types | Yes |
| Order of declarations | Signatures -> implementation |
| Type checking | TS picks the matching signature |
| Alternative | Generic function |
An "all together" example
function format(input: string): string;
function format(input: number): string;
function format(input: boolean): string;
function format(input: string | number | boolean): string {
return `Value: ${input.toString()}`;
}
format("hi"); // string
format(123); // string
format(true); // stringShort Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.