Note: If you're new to TypeScript, check our Getting Started with TypeScript tutorial first.
Function overloading allows you to define multiple function signatures for a single function name.
Each signature describes a different way the function can be called, where the function signatures either have
- different parameter types, or
- different number of parameters.
As a result, the same function will behave differently depending on the arguments passed.
Notes:
- Function overloading helps you write more expressive and type-safe code by clearly specifying the different ways a function can be used.
- Arrow functions cannot be overloaded.
How to Implement Function Overloading in TypeScript?
Function overloading in TypeScript is a little bit different from its counterparts in languages like C, C++, and Java.
Here's how you do it in TypeScript:
Step 1: Define Different Function Signatures
Suppose we need to overload a function named add()
that will accept either two number arguments or two string arguments (but not a mixture of both).
This is how you'll define the function signatures:
// Signature for function with number arguments
function add(a: number, b: number): number;
// Signature for function with string arguments
function add(a: string, b: string): string;
Step 2: Write a Single Function Body to Implement the Overloading
Languages like C++ and Java allow you to write multiple function bodies for overloading.
But in TypeScript, we write a single function body to implement the overloaded functions.
// Function implementation with arguments of any type
function add(a: any, b: any): any {
// Function body
}
Notes:
- Overload signatures do not have function bodies.
- Only one implementation is allowed per function name, but you can declare multiple overload signatures above it.
- The implementation function must be compatible with all overload signatures.
Step 3: Use if...else to Implement Appropriate Code.
Inside the function body, use the if...else
statement to check for the argument types and execute the appropriate code.
Throw an error if the types of the arguments don't match with the ones in the function signatures.
Since our overloaded function can take either two number arguments or two string arguments, any other combination of arguments will be invalid.
// Function implementation
function add(a: any, b: any): any {
if (typeof a === "number" && typeof b === "number") {
return a + b; // Add numbers
}
else if (typeof a === "string" && typeof b === "string") {
return a + b; // Concatenate strings
}
// Throw error if arguments are invalid
throw new Error("Invalid arguments");
}
Next, let's combine these codes into a fully executable program.
Overloading with Different Argument Types
Here's the combined code of what we've learned so far:
// Signature for function with number arguments
function add(a: number, b: number): number;
// Signature for function with string arguments
function add(a: string, b: string): string;
// Function implementation
function add(a: any, b: any): any {
if (typeof a === "number" && typeof b === "number") {
return a + b; // Add numbers
}
else if (typeof a === "string" && typeof b === "string") {
return a + b; // Concatenate strings
}
// Throw error if arguments are invalid
throw new Error("Invalid arguments");
}
// Pass two number arguments to add()
let sum = add(5, 9);
console.log(sum);
// Pass two string arguments to add()
let concatenate = add("Winter", " is coming!");
console.log(concatenate);
// Invalid code: passing a number and a string
// let result = add(343, " Industries");
Output
14 Winter is coming!
Here, we've defined two function signatures for the add()
function: one that accepts two number
arguments and another that accepts two string
arguments.
This is how the program works:
add(5, 9)
- Since both the arguments are numbers, theadd()
function performs numerical addition on them.add("Winter", " is coming!")
- Since both the arguments are strings, theadd()
function concatenates (joins) the two strings.add(343, " Industries")
- This function call is invalid because the first argument is a number while the second is a string. Either both arguments should be numbers, or both should be strings.
More on Overloading with Different Types
In many cases, it's preferable you use union types instead of overloading the function for different argument types.
Let's rewrite the previous example as a demonstration:
// Function with arguments of union type
// The arguments can be either string or number
function add(a: number | string, b: number | string) {
if (typeof a === "number" && typeof b === "number") {
return a + b; // Add numbers
}
else if (typeof a === "string" && typeof b === "string") {
return a + b; // Concatenate strings
}
// Throw error if arguments are invalid
throw new Error("Invalid arguments");
}
// Pass two number arguments to add()
let sum = add(5, 9);
console.log(sum);
// Pass two string arguments to add()
let concatenate = add("Winter", " is coming!");
console.log(concatenate);
// Invalid code: passing a number and a string
// let result = add(343, " Industries");
// Output:
// 14
// Winter is coming!
Overloading with Different Number of Arguments
You can also overload functions using different numbers of arguments. For instance, one function signature can have a single parameter, while another can have two or more parameters.
Let's implement this with the help of the example below:
// Signature with no argument
function greet(): string;
// Signature with a single argument
function greet(name: string): string;
// Signature with two arguments
function greet(name: string, age: number): string;
// Function implementation
// Use optional parameters to account for different argument numbers
function greet(name?: string, age?: number): string {
// Check if two arguments are passed to the function
if (name && age !== undefined) {
return `Hello, ${name}! You are ${age} years old.`;
}
// Check if a single argument is passed
else if (name) {
return `Hello, ${name}!`;
}
// If no argument is passed
else {
return "Hello!";
}
}
// Call without passing any argument
let message: string = greet();
console.log(message);
// Call by passing a single argument
message = greet("Alice");
console.log(message);
// Call by passing two arguments
message = greet("Bob", 30);
console.log(message);
Output
Hello! Hello, Alice! Hello, Bob! You are 30 years old.
Here, greet()
can be called with zero, one, or two arguments.
The implementation uses optional parameters and conditional logic to handle all cases. Passing arguments that don't match the specified types and conditions will result in an error.
Read More: