Kodokon kodokon.com

Genéricos: funciones y tipos genéricos simples

Escribe funciones y tipos reutilizables que conservan toda la precisión de tipos en cada llamada.

9 min · 3 preguntas

Abrir esta lección en Kodokon

Ya usas genéricos sin darte cuenta: string[], Promise<number>... Es hora de escribir los tuyos. Un genérico introduce un parámetro de tipo, una variable reemplazada por un tipo concreto en cada uso. El objetivo: escribir la lógica una sola vez, sin sacrificar la precisión de los tipos.

TYPESCRIPT
function first<T>(items: T[]): T | undefined {
  return items[0];
}

const n = first([10, 20, 30]);
const s = first(["a", "b"]);
T se infiere: n es number | undefined, s es string | undefined

Fíjate en que no especificaste nada en el punto de llamada: TypeScript infiere T a partir del argumento. Un genérico sin restricción acepta cualquier cosa; sin embargo, una función a menudo necesita un mínimo de garantías sobre sus datos. La palabra clave extends impone una forma mínima a T.

TYPESCRIPT
interface HasId {
  id: number;
}

function findById<T extends HasId>(
  items: T[],
  id: number
): T | undefined {
  return items.find((item) => item.id === id);
}
Restricción: T debe tener al menos un id numérico

Los propios tipos pueden ser genéricos. Es el pan de cada día en el código de red: la estructura de la respuesta es estable, solo varía el contenido de data. Un único tipo describe entonces todas tus respuestas de API.

TYPESCRIPT
interface ApiResponse<T> {
  ok: boolean;
  data: T;
}

type UserResponse = ApiResponse<{ name: string }>;

const res: UserResponse = {
  ok: true,
  data: { name: "Ada" },
};
Un tipo genérico parametriza el contenido de data

Prueba de conocimientos

Comprueba que has retenido los puntos clave de esta lección.

  1. En function first<T>(items: T[]): T | undefined, ¿qué representa T?
    • Un tipo concreto definido de una vez por todas
    • Un parámetro de tipo reemplazado en cada llamada
    • El tipo unknown
    • Un atajo para any
  2. ¿Qué garantiza la restricción <T extends HasId>?
    • T es exactamente el tipo HasId
    • T tiene al menos las propiedades de HasId
    • T hereda de la clase HasId
  3. Llamas a first([10, 20, 30]) sin especificar un tipo. ¿Cuál es T?
    • any
    • unknown
    • number
    • 10 | 20 | 30