typescript-sobrecarga-de-funciones

Sobrecarga de funciones en TypeScript

La sobrecarga de funciones permite declarar varias versiones de una función con diferentes parámetros y tipos de retorno. Cada versión de la función (o firma) se llama sobrecarga.

La implementación real de la función debe manejar todas las combinaciones de parámetros definidos en las sobrecargas.

Sintaxis básica de sobrecarga de funciones

Para crear sobrecargas de funciones en TypeScript debemos hacer lo siguiente

  1. Definir las firmas de las funciones sobrecargadas.
  2. Proveer una única implementación de la función que maneje todas las combinaciones de parámetros.

Por ejemplo

// Definición de sobrecargas
function miFuncion(param: string): string;
function miFuncion(param: number): number;

// Implementación de la función
function miFuncion(param: string | number): string | number {
    // hacer cosas

    return "";
}

En este ejemplo, la función miFuncion tiene dos firmas: una que acepta un string y otra que acepta un number. La implementación de la función maneja ambas firmas.

Si intentamos llamar a la función con un tipo, o una cantidad de parámetros que no están admitidas por las firmas, por ejemplo

miFuncion(12);   // esto no da error
miFuncion("12")  // esto no da error

let miObjeto = {};
miFuncion(miObjeto);  // esto da un error, no admite un objeto

miFuncion(12, 12);    // esto da un error, no admite dos int

Recibiremos un error del compilador o del IDE, como el siguiente:

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

Es decir, cuando existen firmas sobrecargadas de una función, TypeScript convierte la función que define el objeto en privada. Por tanto no podemos usarla directamente, y debemos usar obligatoriamente una de sus firmas definidas

Sobrecarga con diferentes tipos de parámetros

Imaginemos una función que puede sumar dos números o concatenar dos cadenas. Podemos usar sobrecarga para definir ambas operaciones.

// Definición de sobrecargas
function combinar(a: string, b: string): string;
function combinar(a: number, b: number): number;

// Implementación de la función
function combinar(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("Tipos de parámetros no coinciden");
}

console.log(combinar("Hola, ", "mundo")); // "Hola, mundo"
console.log(combinar(5, 10)); // 15

Observar cómo la implementación de combinar admite tanto string como number como parámetros, para cumplir con ambas definiciones.

Alternativamente, podríamos haber usado any. Aunque en la medida de lo posible, por limpieza, es mejor que especifiquemos los tipos

Sobrecarga con diferentes cantidades de parámetros

También es posible sobrecargar funciones con diferentes cantidades de parámetros. Por ejemplo, una función que puede tomar uno o dos parámetros:

// Definición de sobrecargas
function mostrarMensaje(mensaje: string): void;
function mostrarMensaje(mensaje: string, veces: number): void;

// Implementación de la función
function mostrarMensaje(mensaje: string, veces?: number): void {
    if (veces === undefined) {
        console.log(mensaje);
    } else {
        for (let i = 0; i < veces; i++) {
            console.log(mensaje);
        }
    }
}

mostrarMensaje("Hola"); // "Hola"
mostrarMensaje("Hola", 3); // "Hola" "Hola" "Hola"

En este ejemplo, veces es un parámetro opcional que permite a la función mostrarMensaje manejar uno o dos argumentos.