TypeScriptDX

Genéricos de TypeScript para Devs Reales

Alejandro Gómez6 min de lectura

Dejá de copiar y pegar tipos. Una guía práctica de genéricos, tipos condicionales y tipos utilitarios que harán tu codebase 10 veces más mantenible.

El problema que resuelven los genéricos

Sin genéricos terminás con tres malas opciones: usar any (inseguro), copiar y pegar el tipo para cada variante (ruidoso), o escribir sobrecargas (verboso). Los genéricos te dan una cuarta opción: escribirlo una vez y dejar que quien llame especifique el tipo.

Funciones genéricas

El genérico más simple es una función que devuelve el mismo tipo que recibe. El <T> es un parámetro de tipo — pensalo como una variable, pero para tipos.

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

const n = first([1, 2, 3]);   // inferido: number | undefined
const s = first(['a', 'b']); // inferido: string | undefined

Restricciones con extends

Podés restringir qué tipos están permitidos como T. Esto te permite acceder a propiedades en T que TypeScript puede garantizar que existen.

function getLabel<T extends { label: string }>(item: T): string {
  return item.label; // seguro — T debe tener label
}

Tipos condicionales

Los tipos condicionales te permiten expresar lógica if-else a nivel de tipos. Son la base de la mayoría de los tipos utilitarios avanzados en la librería estándar de TypeScript.

type EsString<T> = T extends string ? true : false;

type A = EsString<string>; // true
type B = EsString<number>; // false

Tipos utilitarios que vale la pena conocer

  • Partial<T> — hace todas las propiedades opcionales
  • Required<T> — hace todas las propiedades requeridas
  • Pick<T, K> — crea un tipo solo con las claves indicadas
  • Omit<T, K> — crea un tipo sin las claves indicadas
  • ReturnType<F> — extrae el tipo de retorno de una función
  • Awaited<T> — desenvuelve un tipo Promise
Un codebase bien tipado no es uno donde toda variable tiene una anotación explícita. Es uno donde los tipos son precisos, acotados, y hacen trabajo real — detectando bugs antes de correr el código.