¿Por qué enum y botones de radio son la pareja ideal?
\nImagina: estás escribiendo un formulario en TypeScript. Necesitas que el usuario elija una opción entre varias — por ejemplo, nivel de dificultad, estado del pedido o género. ¿Dónde almacenar estas opciones? Podrías hardcodear un array de strings, pero eso no lleva a ningún lado. Cuando haya muchas opciones, te confundirás, y si la lógica de negocio cambia, tendrás que modificar el código en diez lugares.
\nAquí entran en escena los enum (enumeraciones). Permiten definir un conjunto de constantes con nombre que son legibles para los humanos y comprensibles para la máquina. Y los botones de radio son el elemento UI clásico para seleccionar un único valor de una lista. Combinarlos significa obtener un código limpio y mantenible. Suena genial, pero hay un detalle: ¿cómo iterar exactamente un enum para mostrarlo en la plantilla? Esta es la pregunta que atormenta a miles de desarrolladores en Stack Overflow. Vamos a resolverlo de una vez por todas.
\n\nEl problema: un enum no es un array
\nEn TypeScript, un enum no es simplemente una lista de strings. Dependiendo de cómo lo declares (numérico o de strings), se comporta de manera diferente. Un enum numérico crea una relación inversa: clave -> valor y valor -> clave. Uno de strings, solo la directa. Por lo tanto, simplemente escribir for (let item in MyEnum) es una mala idea. Obtendrás no solo las claves deseadas, sino también mapeos inversos no deseados.
Así es como se ve una trampa típica:
\nenum Status {\n Active = 1,\n Inactive = 2,\n Pending = 3\n}\n\n// NO hagas esto\nfor (let key in Status) {\n console.log(key); // "1", "2", "3", "Active", "Inactive", "Pending"\n}\n\n¿Ves? En la consola aparecen tanto los nombres como los valores. Si intentas mostrar esto en botones de radio, el usuario verá números sin sentido. Eso no nos sirve.
\n\nSolución n.º 1: Object.values() para enums de strings
\nLa forma más simple y confiable es usar Object.values(). Este método devuelve un array de los valores de las propiedades enumerables de un objeto. Para enums de strings funciona perfectamente, porque (casi siempre) no tienen mapeo inverso.
Ejemplo: estado del pedido
\nenum OrderStatus {\n New = 'new',\n Processing = 'processing',\n Shipped = 'shipped',\n Delivered = 'delivered',\n Cancelled = 'cancelled'\n}\n\n// Obtenemos el array de valores\nconst statusValues = Object.values(OrderStatus);\n// ['new', 'processing', 'shipped', 'delivered', 'cancelled']\n\n// Ahora se puede mostrar fácilmente en la plantilla (React)\nfunction StatusSelector() {\n return (\n <div>\n {statusValues.map((status) => (\n <label key={status}>\n <input type="radio" name="status" value={status} />\n {status}\n </label>\n ))}\n </div>\n );\n}\n\nTodo es brillantemente simple. Obtuvimos un array de strings y simplemente lo iteramos. Funciona para React, Angular, Vue — cualquier framework.
\n\nSolución n.º 2: Object.keys() + filtrado para enums numéricos
\nCon los enums numéricos la situación es más complicada. Object.values() devolverá no solo las claves de tipo string, sino también los valores numéricos, porque JavaScript los considera "propiedades" del objeto. Necesitamos filtrar solo los strings (claves).
Ejemplo: nivel de acceso
\nenum AccessLevel {\n Guest = 0,\n User = 1,\n Moderator = 2,\n Admin = 3\n}\n\n// Filtramos: dejamos solo los strings (claves)\nconst levelKeys = Object.keys(AccessLevel).filter(key => isNaN(Number(key)));\n// ['Guest', 'User', 'Moderator', 'Admin']\n\n// Si necesitas un array de objetos para una visualización más cómoda\nconst levelOptions = levelKeys.map(key => ({\n label: key,\n value: AccessLevel[key as keyof typeof AccessLevel]\n}));\n// [\n// { label: 'Guest', value: 0 },\n// { label: 'User', value: 1 },\n// ...\n// ]\n\nAhora tienes un array de opciones, donde label es un nombre legible para humanos y value es un código numérico que es conveniente