Language: EN

typescript-sobrecarga-de-funciones

Function Overloading in TypeScript

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 combinations of parameters 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 implementation of the function that handles all combinations of parameters.

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 "";
}

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

If we try to call the function with a type, or a number of parameters that are not supported 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

We will receive a compiler or IDE error, such as the following:

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

That is, when there are overloaded signatures of a function, TypeScript converts the function defining the object to private. Therefore, we cannot use it directly, and we must necessarily 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

Notice how the implementation of combine accepts both string and number as parameters, to meet both definitions.

Alternatively, we could have used any. Although as much as possible, for cleanliness, it is better to specify types

Overloading with different amounts of parameters

It is also possible to overload functions with different amounts 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"

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