Por que enum e radio-buttons são a combinação perfeita?
\nImagine: você está criando um formulário em TypeScript. Precisa permitir que o usuário escolha uma opção entre várias — como nível de dificuldade, status do pedido ou gênero. Onde armazenar essas opções? Você poderia usar um array de strings fixo, mas isso não é escalável. Quando houver muitas opções, você se perderá e, se a lógica de negócio mudar, terá que alterar o código em vários lugares.
\nÉ aqui que os enums (enumerações) entram em cena. Eles permitem definir um conjunto de constantes nomeadas que são legíveis para humanos e compreensíveis para máquinas. Já os radio-buttons são elementos clássicos de UI para selecionar um único valor de uma lista. Unir os dois significa ter um código limpo e de fácil manutenção. Parece ótimo, mas há um detalhe: como exatamente iterar um enum para exibi-lo em um template? Essa é a pergunta que atormenta milhares de desenvolvedores no Stack Overflow. Vamos entender de uma vez por todas.
\n\nO problema: enum não é um array
\nEm TypeScript, um enum não é simplesmente uma lista de strings. Dependendo de como você o declarou (numérico ou string), ele se comporta de maneira diferente. Enums numéricos criam um mapeamento reverso: chave -> valor e valor -> chave. Enums de string criam apenas o mapeamento direto. Portanto, simplesmente escrever for (let item in MyEnum) é uma má ideia. Você obterá não apenas as chaves desejadas, mas também mapeamentos reversos indesejados.
Veja como é a armadilha típica:
\nenum Status {\n Ativo = 1,\n Inativo = 2,\n Pendente = 3\n}\n\n// NÃO faça isso\nfor (let chave in Status) {\n console.log(chave); // "1", "2", "3", "Ativo", "Inativo", "Pendente"\n}\n\nPercebeu? No console aparecem tanto os nomes quanto os valores. Se você tentar exibir isso em radio-buttons, o usuário verá números confusos. Isso não é adequado.
\n\nSolução nº 1: Object.values() para enums de string
\nA maneira mais simples e confiável é usar Object.values(). Este método retorna um array dos valores das propriedades enumeráveis de um objeto. Para enums de string, ele funciona perfeitamente, pois eles (quase sempre) não têm mapeamento reverso.
Exemplo: status do pedido
\nenum OrderStatus {\n Novo = 'novo',\n Processando = 'processando',\n Enviado = 'enviado',\n Entregue = 'entregue',\n Cancelado = 'cancelado'\n}\n\n// Obtém o array de valores\nconst statusValues = Object.values(OrderStatus);\n// ['novo', 'processando', 'enviado', 'entregue', 'cancelado']\n\n// Agora é fácil exibir no template (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\nSimplesmente genial. Obtivemos um array de strings e o iteramos. Funciona para React, Angular, Vue — qualquer framework.
\n\nSolução nº 2: Object.keys() + filtragem para enums numéricos
\nCom enums numéricos, a situação é mais complicada. Object.values() retornará não apenas as chaves de string, mas também os valores numéricos, porque o JavaScript os considera "propriedades" do objeto. Precisamos filtrar apenas as strings (chaves).
Exemplo: nível de acesso
\nenum AccessLevel {\n Convidado = 0,\n Usuario = 1,\n Moderador = 2,\n Admin = 3\n}\n\n// Filtra: mantém apenas as strings (chaves)\nconst levelKeys = Object.keys(AccessLevel).filter(chave => isNaN(Number(chave)));\n// ['Convidado', 'Usuario', 'Moderador', 'Admin']\n\n// Se precisar de um array de objetos para exibição mais amigável\nconst levelOptions = levelKeys.map(chave => ({\n rotulo: chave,\n valor: AccessLevel[chave as keyof typeof AccessLevel]\n}));\n// [\n// { rotulo: 'Convidado', valor: 0 },\n// { rotulo: 'Usuario', valor: 1 },\n// ...\n// ]\n\nAgora você tem um array de opções, onde rotulo é um nome legível e valor é o código numérico, que é conveniente