Enums

Básico
TypeScript
TypeScript
Actualizado: 04/05/2026

Diagrama: tutorial-typescript-enums

Enums numéricos

Los enums (enumerados) en TypeScript permiten definir un conjunto de constantes con nombre. Los enums numéricos son el tipo más básico, donde cada miembro recibe automáticamente un valor entero secuencial comenzando desde 0.

enum Direccion {
  Norte,   // 0
  Sur,     // 1
  Este,    // 2
  Oeste    // 3
}

const miDireccion: Direccion = Direccion.Norte;
console.log(miDireccion); // 0

Cada miembro del enum se convierte en una constante numérica. El primer miembro tiene el valor 0 y los siguientes se incrementan en 1.

Asignación manual de valores

Se pueden asignar valores específicos a los miembros del enum. Los miembros sin valor explícito se incrementan a partir del último valor asignado:

enum CodigoHTTP {
  OK = 200,
  Created = 201,
  BadRequest = 400,
  NotFound = 404,
  InternalServerError = 500
}

function manejarRespuesta(código: CodigoHTTP): void {
  if (código === CodigoHTTP.OK) {
    console.log("Solicitud exitosa");
  } else if (código === CodigoHTTP.NotFound) {
    console.log("Recurso no encontrado");
  } else if (código === CodigoHTTP.InternalServerError) {
    console.log("Error interno del servidor");
  }
}

manejarRespuesta(CodigoHTTP.OK);
manejarRespuesta(CodigoHTTP.NotFound);
enum NivelAcceso {
  Lectura = 1,
  Escritura,      // 2 (automático)
  Admin = 10,
  SuperAdmin      // 11 (automático)
}

console.log(NivelAcceso.Lectura);    // 1
console.log(NivelAcceso.Escritura);  // 2
console.log(NivelAcceso.Admin);      // 10
console.log(NivelAcceso.SuperAdmin); // 11

Reverse mapping

Los enums numéricos generan un mapeo bidireccional: se puede obtener el nombre del miembro a partir de su valor numérico:

enum Temporada {
  Primavera,  // 0
  Verano,     // 1
  Otono,      // 2
  Invierno    // 3
}

const estacion: Temporada = Temporada.Verano;
console.log(estacion);              // 1
console.log(Temporada[estacion]);   // "Verano"
console.log(Temporada[2]);          // "Otono"

Este mapeo bidireccional es exclusivo de los enums numéricos. TypeScript genera un objeto JavaScript que almacena tanto el mapeo directo (nombre a valor) como el inverso (valor a nombre):

// El enum Temporada se compila a algo similar a:
// var Temporada;
// (function (Temporada) {
//     Temporada[Temporada["Primavera"] = 0] = "Primavera";
//     Temporada[Temporada["Verano"] = 1] = "Verano";
//     Temporada[Temporada["Otono"] = 2] = "Otono";
//     Temporada[Temporada["Invierno"] = 3] = "Invierno";
// })(Temporada || (Temporada = {}));

Enums en expresiones switch

Los enums son especialmente útiles en sentencias switch para manejar todos los casos posibles:

enum EstadoPedido {
  Pendiente = 1,
  Procesando,
  Enviado,
  Entregado,
  Cancelado
}

function describirEstado(estado: EstadoPedido): string {
  switch (estado) {
    case EstadoPedido.Pendiente:
      return "El pedido está pendiente de procesamiento";
    case EstadoPedido.Procesando:
      return "El pedido se está procesando";
    case EstadoPedido.Enviado:
      return "El pedido ha sido enviado";
    case EstadoPedido.Entregado:
      return "El pedido ha sido entregado";
    case EstadoPedido.Cancelado:
      return "El pedido ha sido cancelado";
  }
}

console.log(describirEstado(EstadoPedido.Enviado));
console.log(describirEstado(EstadoPedido.Cancelado));

Enums de string

Los enums de string asignan valores de texto a cada miembro. Todos los miembros deben inicializarse explícitamente con un literal de cadena:

enum Idioma {
  Espanol = "es",
  Ingles = "en",
  Frances = "fr",
  Aleman = "de",
  Japones = "ja"
}

const seleccionado: Idioma = Idioma.Espanol;
console.log(seleccionado); // "es"

Los enums de string no admiten asignación automática. Cada miembro debe tener un valor de cadena explícito.

Ventajas de los enums de string

Los valores de string son legibles en logs, en depuración y cuando se serializan a JSON:

enum EventoUsuario {
  Registro = "USUARIO_REGISTRADO",
  InicioSesion = "INICIO_SESION",
  CierreSesion = "CIERRE_SESION",
  CambioPassword = "CAMBIO_PASSWORD"
}

function registrarEvento(evento: EventoUsuario, datos: Record<string, unknown>): void {
  console.log(`[EVENTO] ${evento}`, datos);
}

registrarEvento(EventoUsuario.Registro, { userId: 123, fecha: new Date().toISOString() });
registrarEvento(EventoUsuario.InicioSesion, { userId: 123 });

Integración con APIs

Los enums de string son ideales para representar valores que una API externa espera o devuelve:

enum TipoContenido {
  JSON = "application/json",
  XML = "application/xml",
  FormData = "multipart/form-data",
  TextoPlano = "text/plain"
}

function crearCabeceras(tipo: TipoContenido): Record<string, string> {
  return { "Content-Type": tipo };
}

const cabeceras = crearCabeceras(TipoContenido.JSON);
console.log(cabeceras);

Sin reverse mapping

A diferencia de los enums numéricos, los enums de string no generan mapeo inverso:

enum Color {
  Rojo = "RED",
  Verde = "GREEN",
  Azul = "BLUE"
}

console.log(Color.Rojo);    // "RED"
// console.log(Color["RED"]); // Error: Property 'RED' does not exist on type 'typeof Color'

El JavaScript generado para un enum de string es más simple que para uno numérico, ya que solo contiene el mapeo directo.

Const enums

Los const enums son una variante optimizada que no genera ningun objeto JavaScript en tiempo de ejecución. El compilador sustituye cada referencia al enum por su valor literal:

const enum DiaSemana {
  Lunes,
  Martes,
  Miercoles,
  Jueves,
  Viernes,
  Sabado,
  Domingo
}

const hoy: DiaSemana = DiaSemana.Miercoles;
console.log(hoy); // En el JavaScript generado, esto es simplemente: console.log(2);

Comparación de código generado

La diferencia entre un enum regular y un const enum se observa en el JavaScript resultante:

// Enum regular
enum Color {
  Rojo,
  Verde,
  Azul
}
const miColor = Color.Verde;

// JavaScript generado: crea un objeto Color y accede a el
// var Color;
// (function (Color) { ... })(Color || (Color = {}));
// const miColor = Color.Verde;
// Const enum
const enum ColorConst {
  Rojo,
  Verde,
  Azul
}
const miColorConst = ColorConst.Verde;

// JavaScript generado: sustituye directamente por el valor
// const miColorConst = 1;

El const enum elimina la creación del objeto intermediario, lo que reduce el tamano del JavaScript generado.

Const enums con valores de string

Los const enums funcionan también con valores de cadena:

const enum ErrorCode {
  NotFound = "NOT_FOUND",
  Unauthorized = "UNAUTHORIZED",
  BadRequest = "BAD_REQUEST"
}

function manejarError(code: ErrorCode): void {
  switch (code) {
    case ErrorCode.NotFound:
      console.log("Recurso no encontrado");
      break;
    case ErrorCode.Unauthorized:
      console.log("No autorizado");
      break;
    case ErrorCode.BadRequest:
      console.log("Solicitud incorrecta");
      break;
  }
}

manejarError(ErrorCode.NotFound);

En el JavaScript generado, cada ErrorCode.NotFound se reemplaza por "NOT_FOUND".

Limitaciones de los const enums

Los const enums no existen como objetos en tiempo de ejecución. Esto implica restricciones:

  • No se puede acceder a miembros mediante indexación dinámica (enum[variable]).
  • No se puede iterar sobre los miembros en tiempo de ejecución.
  • No se puede pasar el enum como valor a una función que espera un objeto.
const enum Prioridad {
  Baja = 1,
  Media = 2,
  Alta = 3
}

// Esto funciona: acceso directo
console.log(Prioridad.Alta); // 3

// Esto NO funciona con const enums:
// const nivel = "Alta";
// console.log(Prioridad[nivel]); // Error

En proyectos que usan la opción isolatedModules (habitual con bundlers como Vite o esbuild), los const enums exportados pueden causar problemas. La opción preserveConstEnums en tsconfig.json mitiga estos problemas manteniendo el objeto enum en el código generado.

Enums frente a union types

En TypeScript moderno, los union types de literales son una alternativa ligera a los enums para muchos casos de uso:

// Con enum
enum Rol {
  Admin = "ADMIN",
  Usuario = "USUARIO",
  Invitado = "INVITADO"
}

function verificarAcceso(rol: Rol): boolean {
  return rol === Rol.Admin;
}

console.log(verificarAcceso(Rol.Admin));
// Con union type de literales
type RolLiteral = "ADMIN" | "USUARIO" | "INVITADO";

function verificarAccesoLiteral(rol: RolLiteral): boolean {
  return rol === "ADMIN";
}

console.log(verificarAccesoLiteral("ADMIN"));

Alternativa con as const

Los objetos con as const proporcionan una tercera opción que combina la agrupación de un enum con la ligereza de los literales:

const Roles = {
  Admin: "ADMIN",
  Usuario: "USUARIO",
  Invitado: "INVITADO"
} as const;

type RolValue = typeof Roles[keyof typeof Roles];
// RolValue es: "ADMIN" | "USUARIO" | "INVITADO"

function verificarAccesoConst(rol: RolValue): boolean {
  return rol === Roles.Admin;
}

console.log(verificarAccesoConst(Roles.Admin));
console.log(verificarAccesoConst("USUARIO"));

Criterios de elección

| Criterio | Enum | Union type | as const | |----------|------|------------|----------| | Objeto en runtime | Si | No | Si | | Reverse mapping | Solo numérico | No | No | | Tamano del bundle | Mayor | Mínimo | Medio | | Agrupación de valores | Si | No | Si | | Iteración en runtime | Si | No | Si (Object.values) | | Compatibilidad con isolatedModules | Si (excepto const enum) | Si | Si |

Usar enums cuando: se necesita un objeto en tiempo de ejecución, reverse mapping o la agrupación semántica es importante.

Usar union types cuando: se busca la solución más ligera y no se necesita acceder a los valores como propiedades de un objeto.

Usar as const cuando: se quiere la agrupación de un enum sin la generación de código adicional de los enums regulares.

// Ejemplo práctico: estados de un proceso
type EstadoProceso = "iniciado" | "en_progreso" | "completado" | "fallido";

function avanzarProceso(estado: EstadoProceso): EstadoProceso {
  switch (estado) {
    case "iniciado":
      return "en_progreso";
    case "en_progreso":
      return "completado";
    default:
      return estado;
  }
}

let proceso: EstadoProceso = "iniciado";
proceso = avanzarProceso(proceso);
console.log(proceso); // "en_progreso"
proceso = avanzarProceso(proceso);
console.log(proceso); // "completado"

La elección entre estas opciones depende del caso de uso concreto. En proyectos modernos, la tendencia es preferir union types y as const salvo cuando las caracteristicas específicas de los enums (como el reverse mapping) sean necesarias.

Fuentes y referencias

Documentación oficial y recursos externos para profundizar en TypeScript

Documentación oficial de TypeScript
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, TypeScript es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de TypeScript

Explora más contenido relacionado con TypeScript y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Definir enums numéricos con valores automáticos y manuales. Crear enums de string con valores descriptivos para APIs y logs. Utilizar const enums para optimizar el código JavaScript generado. Comprender el reverse mapping en enums numéricos y sus limitaciones en enums de string. Evaluar cuando usar enums frente a union types de literales.