Fecha de publicación:

Escribí esta nota bajo la influencia de un artículo ya eliminado que proponía usar objetos en lugar de enum en TypeScript.

En vez de:

enum Colors {
  BLUE = 'blue', GREEN = 'green', RED = 'red',
}
function printColor(color: Colors) { console.log(color); }
printColor(Colors.BLUE);
printColor('blue');

se sugería usar:

const Colors = {
  BLUE: 'blue', GREEN: 'green', RED: 'red',
} as const;
type Colors = typeof Colors[keyof typeof Colors];
function printColor(color: Colors) { console.log(color); }
printColor(Colors.BLUE);
printColor('blue');

La ventaja sería poder escribir 'blue' sin importar el módulo que define la enumeración.

En mi artículo sobre la meta última de programar describo una jerarquía de objetivos parecida a la pirámide de Maslow.

Usar literales favorece el primer nivel, la comodidad al escribir. Pero no alcanza el nivel más alto: la capacidad de modificar el sistema con seguridad.

invoice.setState('pending');
order.setState('pending');

Es cómodo, pero al buscar todos los estados pending de pedidos se mezclarán con los de facturas. La importación y el uso de símbolos evitan justamente esa ambigüedad.

En mi código JavaScript uso espacios de nombres inspirados en Zend1:

const TeqFw_Core_Shared_Enum_Sphere = {
  BACK: 'BACK', FRONT: 'FRONT', SHARED: 'SHARED',
};
Object.freeze(TeqFw_Core_Shared_Enum_Sphere);
export default TeqFw_Core_Shared_Enum_Sphere;

Al usarlo, incorporo la enumeración mediante inyección de dependencias y JSDoc:

export default function ({ TeqFw_Core_Shared_Enum_Sphere$: SPHERE }) {
  if (one.sphere === SPHERE.FRONT || one.sphere === SPHERE.SHARED) {
    // ...
  }
}

Así una búsqueda de texto encuentra todos los usos de TeqFw_Core_Shared_Enum_Sphere, y JSDoc ayuda al IDE a localizar cada valor. JavaScript no prohíbe usar literales directamente; es responsabilidad del programador usar las herramientas con criterio. Aunque enum no esté implementado realmente en JavaScript, considero útil escribir como si lo estuviera.