typescript-sobrecarga-de-funciones

Function Overloading in TypeScript

  • 3 min

Function overloading allows declaring multiple versions of a function with different parameters and return types. Each version of the function (or signature) is called an overload.

The actual implementation of the function must handle all parameter combinations defined in the overloads.

Basic Syntax of Function Overloading

To create function overloads in TypeScript we must do the following

  1. Define the signatures of the overloaded functions.
  2. Provide a single function implementation that handles all parameter combinations.

For example

// Overload definitions
function myFunction(param: string): string;
function myFunction(param: number): number;

// Function implementation
function myFunction(param: string | number): string | number {
    // do things

    return "";
}
Copied!

In this example, the function myFunction has two signatures: one that accepts a string and another that accepts a number. The function implementation handles both signatures.

If we try to call the function with a type, or a number of parameters that are not allowed by the signatures, for example

myFunction(12);   // this does not give an error
myFunction("12")  // this does not give an error

let myObject = {};
myFunction(myObject);  // this gives an error, does not accept an object

myFunction(12, 12);    // this gives an error, does not accept two ints
Copied!

We will receive an error from the compiler or IDE, like the following:

The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.

That is, when overloaded signatures of a function exist, TypeScript makes the function that defines the object private. Therefore we cannot use it directly, and we must obligatorily use one of its defined signatures.

Overloading with Different Parameter Types

Imagine a function that can add two numbers or concatenate two strings. We can use overloading to define both operations.

// Overload definitions
function combine(a: string, b: string): string;
function combine(a: number, b: number): number;

// Function implementation
function combine(a: string | number, b: string | number): string | number {
    if (typeof a === "string" && typeof b === "string") {
        return a + b;
    } else if (typeof a === "number" && typeof b === "number") {
        return a + b;
    }
    throw new Error("Parameter types do not match");
}

console.log(combine("Hello, ", "world")); // "Hello, world"
console.log(combine(5, 10)); // 15
Copied!

Observe how the implementation of combine accepts both string and number as parameters, to comply with both definitions.

Alternatively, we could have used any. However, as much as possible, for clarity, it is better to specify the types.

Overloading with Different Numbers of Parameters

It is also possible to overload functions with different numbers of parameters. For example, a function that can take one or two parameters:

// Overload definitions
function showMessage(message: string): void;
function showMessage(message: string, times: number): void;

// Function implementation
function showMessage(message: string, times?: number): void {
    if (times === undefined) {
        console.log(message);
    } else {
        for (let i = 0; i < times; i++) {
            console.log(message);
        }
    }
}

showMessage("Hello"); // "Hello"
showMessage("Hello", 3); // "Hello" "Hello" "Hello"
Copied!

In this example, times is an optional parameter that allows the showMessage function to handle one or two arguments.