Sobrecarga de funciones en TypeScript: por qué no es «magia», sino una herramienta para código inteligente
\n\nSi alguna vez has escrito en JavaScript una función que acepta «ya sea un string, un número, o incluso un array», conoces ese momento desagradable: dentro de la función hay un infierno de if, y desde fuera, una completa incertidumbre para quien la llama. TypeScript resuelve este problema de forma elegante, aunque no siempre obvia. La sobrecarga de funciones (function overloading) no se trata de crear múltiples funciones con el mismo nombre (como en Java o C++). Se trata de declarar múltiples firmas para una sola implementación.
En 2025, cuando TypeScript se ha convertido en el estándar de facto para proyectos serios de frontend y backend, saber configurar correctamente la sobrecarga no es un «lujo», sino una habilidad que hace que tu código sea legible, type-safe y fácil de usar en equipo. Analicemos cómo funciona, en qué se equivocan los principiantes y qué patrones deberías adoptar.
\n\n¿Qué es realmente la sobrecarga de funciones?
\n\nImagina que escribes una función formatDate. Debería ser capaz de:
- \n
- Aceptar un objeto
Datey devolver un string. \n - Aceptar un string en formato ISO y devolver un string. \n
- Aceptar un número (timestamp) y devolver un string. \n
Si simplemente escribes function formatDate(input: Date | string | number): string, TypeScript no podrá indicar qué tipo exacto estás pasando en una llamada concreta. El IDE mostrará el tipo general y perderás el autocompletado. La sobrecarga resuelve esto:
// Firmas de sobrecarga (overload signatures)\nfunction formatDate(input: Date): string;\nfunction formatDate(input: string): string;\nfunction formatDate(input: number): string;\n\n// Implementación (implementation signature)\nfunction formatDate(input: Date | string | number): string {\n if (input instanceof Date) {\n return input.toISOString();\n } else if (typeof input === 'string') {\n return new Date(input).toISOString();\n } else {\n return new Date(input).toISOString();\n }\n}\n\nAhora, cuando llamas a formatDate(new Date()), TypeScript sabe que devuelve un string y sugiere los tipos. No hay magia: hay tipado estricto.
Regla nº1: las firmas de sobrecarga no pueden ser implementaciones
\n\nEl error más común de los principiantes es intentar escribir el cuerpo de la función en cada firma. No hagas esto:
\n\n// ❌ Error: duplicación de implementación\nfunction foo(x: number): number {\n return x * 2;\n}\nfunction foo(x: string): string {\n return x.toUpperCase();\n}\n\nTypeScript no soporta múltiples implementaciones con el mismo nombre. Siempre una implementación, varias declaraciones.
\n\nRegla nº2: el orden de las firmas importa
\n\nTypeScript verifica las firmas de arriba a abajo. La primera firma que coincida determina el tipo de retorno. Por lo tanto:
\n- \n
- Coloca los tipos más específicos arriba (por ejemplo,
stringantes queany). \n - Evita firmas superpuestas que puedan confundir al compilador. \n
// Bien: primero el caso específico\nfunction createButton(label: string, disabled?: boolean): HTMLButtonElement;\nfunction createButton(options: { label: string; disabled?: boolean }): HTMLButtonElement;\nfunction createButton(labelOrOptions: string | { label: string; disabled?: boolean }, disabled?: boolean): HTMLButtonElement {\n // implementación\n}\n\nRegla nº3: usa Union Types si tienes más de 3 firmas
\n\nLa sobrecarga es una herramienta poderosa, pero no abuses de ella. Si tienes 5 o más firmas, el código se vuelve ilegible. En 2025, una buena práctica es:
\n- \n
- Hasta 3 firmas — usa sobrecarga. \n
- Más de 3 — considera usar un
Union Typeo