Generics y tipificación en JavaScript: cómo escribir código sin errores

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Por qué la tipificación es una superpotencia, no una carga

\n\n

Imagine: escribe código, todo funciona, es feliz. Y luego — ¡pum! — aparece un error rojo en la consola: Cannot read property 'name' of undefined. ¿Le suena? Bienvenido al mundo de JavaScript sin tipos. Pero hay una buena noticia: el JavaScript moderno (y especialmente TypeScript) ofrece una herramienta poderosa: Generics (genéricos). No es solo "otra característica", sino una forma real de hacer el código más limpio, seguro y comprensible.

\n\n

En este artículo, analizaremos qué es la tipificación en JavaScript, cómo funcionan los generics y por qué debería usarlos en cada proyecto. Sin teoría aburrida, solo ejemplos vivos y consejos prácticos.

\n\n

¿Qué son los Generics y para qué sirven?

\n\n

Generics (tipos genéricos) es un mecanismo que permite escribir funciones, clases e interfaces que trabajan con diferentes tipos de datos, pero manteniendo una tipificación estricta. En términos simples: crea código "universal" que se adapta automáticamente al tipo de datos con el que trabaja.

\n\n

Sin genéricos, escribiría algo como:

\n\n
function identity(arg: any): any {\n    return arg;\n}
\n\n

¿El problema? any destruye toda la tipificación. Pierde información sobre el tipo y el compilador no podrá advertirle sobre un error. Con Generics es diferente:

\n\n
function identity<T>(arg: T): T {\n    return arg;\n}\n\n// Uso\nlet num = identity<number>(42); // tipo number\nlet str = identity<string>("Hola"); // tipo string
\n\n

¿Magia? No, solo tipificación inteligente. El tipo T es un marcador de posición que se reemplaza por el tipo real al llamar a la función.

\n\n

Generics vs any: la batalla por la seguridad

\n\n

Muchos principiantes preguntan: "¿Por qué complicarse con genéricos si puedo usar any?" La respuesta es simple: la seguridad de tipos no es solo "para que se vea bonito", sino para prevenir errores en tiempo de ejecución.

\n\n

Mire este ejemplo sin Generics:

\n\n
function getLength(data: any): number {\n    return data.length; // si data es un número, dará error\n}\n\ngetLength(42); // undefined en tiempo de ejecución\n
\n\n

Con genéricos, indica explícitamente que la función trabaja con arrays o cadenas:

\n\n
function getLength<T extends { length: number }>(data: T): number {\n    return data.length;\n}\n\ngetLength([1,2,3]); // 3\ngetLength("hello"); // 5\n// getLength(42); // Error de compilación — un número no tiene length\n
\n\n

¿Ve la diferencia? El error se detecta al escribir el código, no en producción. Esta es la esencia de la tipificación avanzada.

\n\n

Ejemplos prácticos de Generics en JavaScript

\n\n

Veamos algunos escenarios reales donde los genéricos realmente salvan el día.

\n\n

1. Funciones genéricas para trabajar con arrays

\n\n

Supongamos que escribe una utilidad para extraer el primer elemento de un array:

\n\n
function first<T>(arr: T[]): T | undefined {\n    return arr[0];\n}\n\nconst numbers = [10, 20, 30];\nconst firstNum = first(numbers); // tipo number | undefined\n\nconst strings = ["a", "b", "c"];\nconst firstStr = first(strings); // tipo string | undefined\n
\n\n

Sin genéricos, tendría que escribir dos funciones separadas o usar any. Con la tipificación de JavaScript mediante Generics, una función funciona para todos los tipos.

\n\n

2. Clases genéricas para almacenar datos

\n\n

Imagine que crea un envoltorio simple para almacenar un valor:

\n\n
class Box<T> {\n    private content: T;\n\n    constructor(initial: T) {\n        this.content = initial;\n    }\n\n    getValue(): T {\n        return this.content;\n    }\n\n    setValue(value: T): void {\n        this.content = value;\n    }\n}\n\n// Uso\nconst numberBox                

Blogs

Book Recommendations