Entrada / 15 feb. 2026

Adiós a los if/else infinitos en TypeScript con Object Lookup

Por qué convertir cadenas de condicionales en objetos de mapeo tipados hace el código de TypeScript más claro, más seguro y mucho más fácil de mantener.

Adiós a los if/else infinitos en TypeScript con Object Lookup

👉 Ver en YouTube

Hay un momento en el que un if deja de ser una solución rápida y empieza a convertirse en deuda técnica.

Todo arranca con una condición. Luego llega otro requerimiento. Después otro. Y cuando te das cuenta, tienes una cadena de if / else if que nadie quiere tocar porque quitar una rama podría romper todo.

Ese es exactamente el problema que resuelve este video: cómo pasar de una lógica frágil basada en condicionales a un enfoque más limpio y orientado a datos usando objetos y TypeScript.

El problema real de las cadenas de condicionales

El problema no es solo visual.

Las estructuras largas de if suelen producir código que es:

  • más difícil de leer
  • más difícil de extender con seguridad
  • más fácil de romper cuando cambian los requisitos
  • menos compatible con el autocompletado y la validación de TypeScript

Cuando la entrada es solo un string, TypeScript casi no puede ayudarte. Pierdes la lista de valores permitidos, se cuelan casos inválidos con más facilidad y el compilador deja de actuar como red de seguridad.

Por eso este tipo de código se siente tan peligroso de editar.

El patrón de object lookup

La idea central del video es simple: dejar de hacer la misma pregunta una y otra vez con condicionales y reemplazar esa lógica por un objeto de mapeo.

En lugar de esto:

function getRoleLabel(role: string) {
  if (role === "admin") return "Acceso total";
  if (role === "editor") return "Puede editar contenido";
  if (role === "guest") return "Solo lectura";
  return "Rol desconocido";
}

Puedes pasar a algo así:

const roleLabels = {
  admin: "Acceso total",
  editor: "Puede editar contenido",
  guest: "Solo lectura",
};

function getRoleLabel(role: string) {
  return (
    roleLabels[role as keyof typeof roleLabels] ??
    "Rol desconocido"
  );
}

Conceptualmente, esto se parece mucho más a una tabla de decisiones que a un árbol de control de flujo. La lógica deja de ser una secuencia de comparaciones y pasa a ser una relación directa entre valores.

Y eso importa porque el código deja de girar alrededor de ramas y empieza a expresar datos.

Por qué se siente más limpio de inmediato

Un objeto de mapeo reduce ruido.

Ya no estás leyendo comparaciones repetidas. Estás viendo las opciones permitidas directamente.

Eso normalmente te da:

  • menos líneas
  • más claridad en la intención
  • cambios más simples cuando aparece un caso nuevo
  • una separación más clara entre datos y comportamiento

Es una de esas refactorizaciones en las que la mejora de legibilidad aparece incluso antes de sacar partido de las partes más avanzadas de TypeScript.

Dónde TypeScript empieza a brillar

En el video, el siguiente paso es tipar mejor ese patrón usando un tipo unión para las claves permitidas.

type UserRole = "admin" | "editor" | "guest";

const roleLabels: Record<UserRole, string> = {
  admin: "Acceso total",
  editor: "Puede editar contenido",
  guest: "Solo lectura",
};

function getRoleLabel(role: UserRole) {
  return roleLabels[role];
}

Aquí es donde el patrón deja de ser solo “JavaScript más limpio” y se convierte en TypeScript bien aprovechado.

Ahora obtienes:

  • autocompletado para los roles válidos
  • errores en compilación si pasas un valor inválido
  • garantías de que cada rol permitido tiene un valor asociado
  • una firma de función que documenta el contrato con claridad

Ese último punto importa mucho.

La función ya no acepta cualquier cadena esperando que salga bien. Declara exactamente qué entiende el sistema.

keyof y typeof permiten derivar las claves automáticamente

Una de las mejores extensiones del video es la variante con keyof typeof.

const roleLabels = {
  admin: "Acceso total",
  editor: "Puede editar contenido",
  guest: "Solo lectura",
};

type UserRole = keyof typeof roleLabels;

Esto funciona porque:

  • typeof captura el tipo del valor roleLabels
  • keyof convierte ese tipo de objeto en una unión con sus claves

Así, TypeScript deriva por ti "admin" | "editor" | "guest".

Eso es potente porque la fuente de verdad pasa a ser el propio objeto. Si agregas una nueva clave, la unión se actualiza sola.

Para tablas de mapeo pequeñas, esta suele ser una opción muy cómoda porque mantiene el tipo y los datos sincronizados casi sin esfuerzo extra.

Una mejora útil para producción: Record

El video gira alrededor de la idea del objeto de mapeo, pero en código de producción también conviene conocer Record.

type UserRole = "admin" | "editor" | "guest";

const roleLabels: Record<UserRole, string> = {
  admin: "Acceso total",
  editor: "Puede editar contenido",
  guest: "Solo lectura",
};

Record<Keys, Type> sirve cuando quieres definir primero las claves válidas y obligar a que el objeto implemente por completo ese contrato.

Eso lo vuelve especialmente útil cuando el dominio ya está claro y quieres que los casos faltantes fallen de inmediato durante el desarrollo.

Sobre el argumento de O(1)

En el video se menciona que se pasa de O(n) a O(1).

Como idea general, eso tiene sentido si comparas un acceso directo a una propiedad contra una secuencia de comparaciones. Pero en el código de aplicación del día a día, la mejora más importante casi nunca es el rendimiento puro.

Es la mantenibilidad.

La ganancia real es que una tabla de mapeo es más fácil de extender, más fácil de auditar y mucho más fácil de modelar con TypeScript.

Así que sí: el acceso suele ser eficiente. Pero el verdadero valor de esta refactorización está en el diseño.

Cuando este patrón es la herramienta correcta

Un object lookup funciona especialmente bien cuando:

  • una clave de entrada se traduce directamente en un valor
  • una clave de entrada se traduce directamente en una función
  • los casos válidos son finitos y explícitos
  • quieres que TypeScript obligue cobertura y autocompletado

Encaja muy bien para labels, handlers, configuraciones, mensajes según rol, feature flags y tablas de despacho ligeras.

Cuando tal vez necesitas otra cosa

No todo condicional debería convertirse en un objeto de mapeo.

Si cada rama tiene comportamiento más rico, cambios de estado o varias operaciones relacionadas, puede que una estrategia o un diseño polimórfico sea una mejor evolución.

Eso coincide con una idea más amplia de refactoring: cuando los condicionales empiezan a multiplicarse por todo el código, muchas veces están revelando que el diseño necesita límites más claros.

Dicho de otro modo, un object lookup es excelente para mapeos directos. No necesariamente es la abstracción final para todos los escenarios.

El takeaway

La lección aquí es más grande que reemplazar if por objetos.

Se trata de pasar de ramas imperativas a modelos explícitos.

Cuando las opciones válidas viven dentro de un objeto tipado y TypeScript puede derivar o forzar sus claves, el compilador vuelve a trabajar a tu favor.

Obtienes código que es:

  • más fácil de leer
  • más seguro de extender
  • mejor documentado por sus tipos
  • menos propenso a pudrirse cuando crecen los requisitos

Eso no es un hack.

Es mejor diseño.