CodeForge

TypeScript de Cero a Experto / Funciones e interfaces

Sobrecargas: una función, varias firmas

Teoría18 min20 XP

A veces una función se comporta —y tipa— distinto según cómo la llames: pásale un número y devuelve un número; pásale un array y devuelve un array. Las SOBRECARGAS te dejan darle varias firmas públicas a una sola función. Es una técnica de nicho pero elegante; hoy la conoces y aprendes cuándo hay algo mejor.

El empleado que atiende varias ventanillas

Declarar sobrecargas

Escribes las firmas públicas ANTES de la función, y luego UNA implementación que las cumple todas:

overloads.ts
// las FIRMAS públicas (lo que ve quien la usa):
function duplicar(valor: number): number;
function duplicar(valor: string): string;
// la IMPLEMENTACIÓN (oculta para quien llama; debe cubrir todos los casos):
function duplicar(valor: number | string): number | string {
if (typeof valor === "number") return valor * 2;
return valor + valor;
}

// gracias a las firmas, TS sabe el tipo EXACTO de retorno según lo que pases:
const n = duplicar(5);       // TS: number (no number | string)
const s = duplicar("ab");    // TS: string
n.toFixed(2);   // ✓ TS sabe que n es number
s.toUpperCase(); // ✓ TS sabe que s es string

Lo valioso: sin sobrecargas, duplicar devolvería number | string siempre, y tendrías que estrechar el resultado cada vez. Con ellas, TS sabe que duplicar(5) devuelve EXACTAMENTE number —el retorno preciso según la entrada. Las dos primeras líneas son las ventanillas públicas; la tercera es el empleado que las resuelve por dentro.

La firma de implementación es privada

Cuándo sobrecargar… y cuándo no

Las sobrecargas son poderosas pero a menudo hay algo más simple:

alternativas.ts
// ❌ sobrecarga innecesaria: si el retorno NO cambia según la entrada,
//    una simple unión basta y es más clara:
function longitud(x: string | any[]): number {
return x.length;   // sin overloads: el retorno siempre es number
}

// ✅ sobrecarga justificada: el TIPO DE RETORNO depende del de entrada
//    (number→number, string→string) — eso una unión sola no lo captura bien.

// para transformaciones genéricas, un GENÉRICO (módulo 5) suele ganar:
function primero<T>(arr: T[]): T | undefined {
return arr[0];   // funciona para cualquier tipo, sin repetir firmas
}

Ese ejemplo es real: así es como TypeScript tipa document.createElement —con sobrecargas—, para que createElement("a") te dé un HTMLAnchorElement con .href y createElement("img") un HTMLImageElement con .src. Cuando veas ese autocompletado preciso según el tag, ya sabes qué hay detrás.

Tienes function envolver<T>(x: T): T[] { return [x]; } que mete cualquier valor en un array. ¿Deberías convertirla en sobrecargas (una por tipo)?

Mini-reto

Distingue las herramientas: 1) escribe una sobrecarga JUSTIFICADA —function convertir(x: string): number y function convertir(x: number): string— con su implementación (string→Number(x), number→String(x)); 2) comprueba que convertir("42") tipa como number y convertir(42) como string; 3) reflexiona: ¿podría un genérico hacer esto? (No: el retorno es el OPUESTO de la entrada, justo el caso donde las sobrecargas ganan.)

Qué sigue

Cierras el módulo con un reto que junta funciones tipadas, un callback y una interface trabajando en equipo. Luego, el módulo 4 aborda la técnica más característica de TypeScript: el NARROWING —enseñarle al compilador a razonar sobre tus datos como lo haces tú.