Generics en TypeScript: guía completa sobre genéricos

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 a Generics en TypeScript



TypeScript es un lenguaje fuertemente tipado que extiende las capacidades de JavaScript agregando tipado estático. Sin embargo, una de sus características más potentes y flexibles es el mecanismo de Generics. Si alguna vez has escrito código que debe funcionar con diferentes tipos de datos, pero manteniendo la seguridad de tipos, entonces Generics es exactamente lo que necesitas.



Imagina que creas una función universal que puede aceptar arrays de números, strings u objetos. Sin generics, tendrías que usar el tipo any (lo que anula todos los beneficios de TypeScript) o escribir funciones separadas para cada tipo. Generics resuelve este problema de manera elegante y segura. En este artículo, analizaremos qué son los Generics, para qué sirven y cómo usarlos eficazmente en proyectos reales.



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



Generics es un mecanismo que permite crear componentes (funciones, clases, interfaces) capaces de trabajar con diferentes tipos de datos sin perder información sobre los tipos. En lugar de fijar un tipo específico, se utiliza un parámetro de tipo que se sustituye en el momento de la llamada.



El problema sin Generics



Supongamos que quieres escribir una función que devuelva el primer elemento de un array. Sin generics, podría verse así:



function getFirstElement(arr: any[]): any {  return arr[0];}

const num = getFirstElement([1, 2, 3]); // Tipo 'any' — perdimos la informaciónconsole.log(num.toUpperCase()); // Error en tiempo de ejecución, pero TypeScript no dice nada


Aquí usamos any, y TypeScript no puede advertirnos que num es un número, no un string. Esto provoca posibles errores en tiempo de ejecución.



Solución con Generics



Ahora reescribamos la misma función usando generics:



function getFirstElement<T>(arr: T[]): T {  return arr[0];}

const num = getFirstElement([1, 2, 3]); // Tipo 'number'const str = getFirstElement(['a', 'b', 'c']); // Tipo 'string'

// num.toUpperCase(); // Error de compilación — TypeScript sabe que num es un número


El símbolo <T> es el parámetro de tipo. Actúa como un placeholder: cuando llamamos a la función con un array de números, T se convierte en number, y el valor devuelto también obtiene el tipo number. De esta manera, mantenemos un tipado estricto sin perder flexibilidad.



Cómo usar Generics: escenarios principales



Los Generics no solo se aplican en funciones, sino también en clases, interfaces y tipos. Veamos los escenarios más comunes.



Generics en funciones



El caso más simple y frecuente son las funciones que trabajan con datos de diferentes tipos. Por ejemplo, una función para crear un par clave-valor:



function createPair<K, V>(key: K, value: V): { key: K; value: V } {  return { key, value };}

const pair = createPair('id', 123); // { key: string; value: number }console.log(pair.key.toUpperCase()); // Funciona// pair.key.toFixed(); // Error — key es un string


Aquí usamos dos parámetros de tipo: K para la clave y V para el valor. TypeScript deduce automáticamente los tipos basándose en los argumentos.



Generics en clases



Los generics son ideales para crear clases universales, como pilas, colas o almacenes de datos:



class Stack<T> {  private items: T[] = [];

push(item: T): void { this.items.push(item); }

pop(): T | undefined { return this.items.pop(); }

peek(): T | undefined { return this.items[this.items.length - 1]; }}

const numberStack = new Stack<number>();numberStack.push(10);numberStack.push(20);console.log(numberStack

Blogs

Book Recommendations