TypeScript Generics: escribiendo código flexible sin duplicación

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

Introducción: ¿por qué sin genéricos TypeScript pierde la mitad de su fuerza?



Imagina que eres un arquitecto que cada vez diseña un edificio desde cero, incluso si solo necesita construir otro garaje igual. Así se siente aproximadamente un desarrollador que escribe la misma función para números, cadenas y arreglos, sin usar TypeScript generics. ¿Suena familiar? Si ya dominas los tipos básicos en TypeScript, pero sientes que escribes demasiado código duplicado, este artículo es para ti.



Generics (genéricos) es un mecanismo que permite crear componentes (funciones, clases, interfaces) que trabajan con diferentes tipos, en lugar de uno específico. En lugar de copiar código, lo escribes una vez y el tipo se sustituye automáticamente. En este artículo, analizaremos cómo funciona la programación genérica en TypeScript, mostraremos ejemplos de código reales y daremos consejos prácticos que harán tu código más limpio y seguro.



Somos PythonLib, y hoy hablamos de TypeScript porque sin él, el desarrollo frontend moderno es impensable. ¡Vamos allá!



¿Qué son los genéricos en TypeScript y para qué sirven?



Comencemos con un ejemplo simple. Supongamos que quieres escribir una función que devuelve el argumento que recibe (función identidad).



// Sin genéricos — hay que usar anyfunction identity(arg: any): any {    return arg;}

// O escribir sobrecargas para cada tipofunction identityNumber(arg: number): number { return arg; }function identityString(arg: string): string { return arg; }


La primera opción destruye el tipado — pierdes información sobre el tipo. La segunda te obliga a crear montones de funciones idénticas. Los genéricos de TypeScript resuelven este problema de forma elegante:



function identity<T>(arg: T): T {    return arg;}

const num = identity<number>(42); // tipo numberconst str = identity('hello'); // tipo string (inferencia de tipo)const bool = identity(true); // tipo boolean


El símbolo <T> es el parámetro de tipo. Puedes nombrarlo como quieras (a menudo se usan T, U, V), pero es mejor dar nombres significativos si hay varios. Cuando llamas a la función, TypeScript sustituye el tipo real en lugar de T. Si no se especifica el tipo explícitamente, el compilador lo infiere automáticamente del argumento.



Así, los tipos genéricos (Generics) permiten mantener un tipado estricto donde antes había que usar any. Esto reduce la cantidad de errores y hace que el código sea autodocumentado.



Sintaxis de los genéricos: de lo simple a lo complejo



Funciones genéricas



Ya vimos el ejemplo básico. Compliquémoslo: una función que recibe un arreglo y devuelve su primer elemento.



function getFirst<T>(arr: T[]): T | undefined {    return arr[0];}

const firstNumber = getFirst([1, 2, 3]); // number | undefinedconst firstString = getFirst(['a', 'b', 'c']); // string | undefined


Observa: T[] es una abreviatura de Array<T>. Puedes usar cualquier forma.



Interfaces genéricas



Las interfaces con genéricos son una herramienta poderosa para describir estructuras de datos. Por ejemplo, una respuesta API tipada:



interface ApiResponse<T> {    data: T;    status: number;    message: string;}

// Usoconst userResponse: ApiResponse<{ id: number; name: string }> = { data: { id: 1, name: 'Alice' }, status: 200, message: 'OK'};


Ahora una misma interfaz puede describir respuestas para usuarios, productos, pedidos — basta con sustituir el tipo adecuado.



Clases genéricas



Las clases también pueden ser genéricas. Un ejemplo clásico es una cola (Queue):



c                

Blogs

Book Recommendations