Genéricos y narrowing

Aprende a crear código reutilizable sin perder tipos y a refinar valores inciertos con comprobaciones seguras.

Aquí TypeScript deja de ser solo “poner tipos” y empieza a volverse realmente potente.

Los genéricos permiten reutilizar código sin perder información de tipos. El narrowing permite pasar de algo incierto a algo seguro.


Genéricos

function identidad<T>(valor: T): T {
  return valor;
}

const a = identidad<string>('hola');
const b = identidad<number>(42);

T representa “el tipo que venga”. La función devuelve exactamente ese mismo tipo.


Un ejemplo útil

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

const nombre = primerElemento(['Ana', 'Luis']); // string | undefined
const numero = primerElemento([10, 20]); // number | undefined

Sin genéricos perderías precisión y acabarías en any.


Genéricos en types

type ApiResponse<T> = {
  ok: boolean;
  data: T;
};

const respuesta: ApiResponse<string[]> = {
  ok: true,
  data: ['uno', 'dos'],
};

Esto aparece muchísimo al trabajar con APIs.


Qué es narrowing

Cuando una variable puede ser de varios tipos, TypeScript no te deja usar propiedades o métodos específicos hasta que demuestres cuál es el caso real.

function imprimir(valor: string | number) {
  if (typeof valor === 'string') {
    return valor.toUpperCase();
  }

  return valor.toFixed(2);
}

Dentro del if, TypeScript ha estrechado el tipo a string.


Narrowing con in

type Gato = { maullar: () => void };
type Perro = { ladrar: () => void };

function hablar(animal: Gato | Perro) {
  if ('maullar' in animal) {
    animal.maullar();
  } else {
    animal.ladrar();
  }
}

Narrowing con discriminated unions

type Exito = { estado: 'ok'; data: string[] };
type Fallo = { estado: 'error'; mensaje: string };

type Resultado = Exito | Fallo;

function procesar(resultado: Resultado) {
  if (resultado.estado === 'ok') {
    return resultado.data.length;
  }

  return resultado.mensaje;
}

Este patrón es excelente para respuestas de API y estados de UI.


Idea práctica

  • usa genéricos cuando una función o tipo deba adaptarse a distintos tipos
  • usa narrowing para convertir incertidumbre en seguridad

En la última lección cerramos con tsconfig, modo estricto y reglas que sí valen la pena.