Saltar al contenido principal
eLearner.app
Módulo 3 · Lección 2 de 26/14 en el curso~15 min
Lecciones del módulo (2/2)

Genéricos Fundamentales

Los Generics (programación genérica) son una de las características más potentes de TypeScript. Permiten escribir componentes, funciones e interfaces flexibles y reutilizables que pueden trabajar con diferentes tipos de datos, manteniendo la máxima seguridad de tipos (type safety) y evitando el uso de any.


Las Funciones Genéricas

Piensa en un generic como una variable para los tipos. Consideremos una función que devuelve el valor pasado como argumento:

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

La letra T (abreviatura de Type) es un marcador de posición para el tipo. Cuando llamamos a identity, TypeScript captura el tipo del argumento pasado y establece automáticamente T a ese tipo:

TS
const str = identity<string>('Hello'); // T è string
const num = identity(42); // T è number (inferito automaticamente!)

Interfaces y Alias Genéricos

Los generics también se pueden aplicar a interfaces y alias de tipo para definir contenedores o estructuras de datos genéricas:

TS
interface Box<T> {
  content: T;
}

const stringBox: Box<string> = { content: 'TypeScript' };
const numberBox: Box<number> = { content: 42 };

Múltiples Parámetros de Tipo

Podemos definir funciones o tipos que utilicen múltiples variables de tipo (ej. T y U):

TS
function mergeObjects<T, U>(obj1: T, obj2: U): T & U {
  return { ...obj1, ...obj2 };
}

Restricciones en los Generics (Generic Constraints)

A veces queremos limitar los tipos aceptados por un generic. Podemos usar la palabra clave extends para agregar una restricción (constraint).

Por ejemplo, si queremos que el tipo genérico tenga siempre una propiedad length (como cadenas o arrays):

TS
interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(arg: T): void {
  console.log(arg.length); // Sicuro! Sappiamo che arg ha 'length'
}

logLength('Hello'); // Valido
logLength([1, 2, 3]); // Valido
// logLength(42); // Errore: number non ha la proprietà length!

Pruébalo tú

Ejercicio 1: Función Genérica Identity

Ejercicio#ts.m3.l2.e1
Intentos: 0Cargando...

Completa la función genérica identity de modo que acepte un parámetro value de tipo genérico T y lo devuelva sin modificaciones.

Cargando editor...
Mostrar pista

El tipo de retorno debe ser el mismo tipo genérico T del parámetro.

Solución disponible después de 3 intentos

Ejercicio 2: Contenedor Genérico Box

Ejercicio#ts.m3.l2.e2
Intentos: 0Cargando...

Define una interfaz genérica llamada Box que acepte un parámetro de tipo T y tenga una única propiedad llamada content de tipo T.

Cargando editor...
Mostrar pista

Usa la sintaxis interface Box<T> { content: T; }.

Solución disponible después de 3 intentos

Ejercicio 3: Restricción Genérica (Constraint)

Ejercicio#ts.m3.l2.e3
Intentos: 0Cargando...

Escribe una función genérica llamada getLength que acepte un parámetro arg. arg debe estar restringido a una interfaz que posea una propiedad length (número). La función debe devolver arg.length.

Cargando editor...
Mostrar pista

Declara la función como getLength<T extends HasLength>(arg: T): number y devuelve arg.length.

Solución disponible después de 3 intentos

Ejercicio 4: Pareja Genérica Pair

Ejercicio#ts.m3.l2.e4
Intentos: 0Cargando...

Define una interfaz genérica Pair<T, U> con dos propiedades: first de tipo T y second de tipo U. Después, crea una función genérica makePair que acepte first (de tipo T) y second (de tipo U) y devuelva un objeto que implemente Pair<T, U>.

Cargando editor...
Mostrar pista

Usa la sintaxis para dos parámetros genéricos Pair<T, U> y define makePair en consecuencia.

Solución disponible después de 3 intentos