Enum em TypeScript: numérico, string, const e as alternativas | We.Inc
Gere enums numéricos, de string e const a partir dos seus próprios nomes de membros, veja o JavaScript exato que cada um gera e compare com objetos as const e uniões de literais.
Um enum dá a um conjunto de constantes nomeadas um único tipo. Enums numéricos contam a partir de 0 e também mapeiam números de volta para nomes; enums de string precisam de um literal por membro e não têm mapeamento reverso; const enums são inseridos no lugar e desaparecem. Diferente da maior parte do TypeScript, enums comuns geram JavaScript de verdade, por isso muitos times preferem objetos as const.
Cinco formas de modelar um conjunto fixo de valores
Estilo
Gera JavaScript?
Mapeamento reverso
Aceita um literal puro?
Enum numérico
Sim, um objeto
Sim, de número para nome
Números que correspondem a um membro
Enum de string
Sim, um objeto
Não
Não, precisa usar Enum.Member
const enum
Não, valores inseridos no lugar
Não
Conforme o tipo do enum
Objeto as const
Sim, um objeto simples
Não (escreva um se precisar)
Sim
União de literais
Não, apagada
Não
Sim
Digite nomes de membros no gerador e alterne entre os estilos. Ele escreve a declaração em TypeScript e o JavaScript que o compilador geraria, para você ver o custo de cada escolha antes que ela chegue ao seu bundle.
Digite os nomes dos membros separados por vírgulas, por exemplo Draft, Review, Live.
Para enums numéricos, defina o número inicial; os membros seguintes contam a partir dele.
Escolha um estilo para ver a declaração, o JavaScript gerado e como usá-lo.
Copie a versão que combina com o seu projeto.
Escolha enums de string ou objetos as const para valores que saem do seu programa, como campos de API ou colunas de banco de dados. Uma linha de log que diz live é mais fácil de ler que 2.
Nunca reordene nem insira membros no meio de um enum numérico que é armazenado em algum lugar. Todos os números seguintes mudam e os dados salvos antes passam a significar outra coisa.
Evite const enum em bibliotecas publicadas. Quem compila com isolatedModules ou com um removedor de tipos não consegue inserir valores vindos de outro arquivo.
Ative erasableSyntaxOnly se você roda arquivos .ts com o type stripping do Node; ele aponta os enums antes que falhem em tempo de execução.
Perguntas frequentes
O que é um mapeamento reverso?
Para enums numéricos, o tsc guarda as duas direções no objeto, então Direction.Up é 0 e Direction[0] é a string Up. Membros de string não ganham entrada reversa, porque o valor poderia colidir com o nome de outro membro.
Por que não consigo passar uma string simples para uma função que recebe um enum de string?
Membros de enum de string são tipos distintos. O compilador avisa que o literal não pode ser atribuído ao enum, então quem chama precisa escrever Status.Draft. Se você quer que quem chama passe o literal, use uma união de literais de string.
Como percorro os valores de um enum?
Para um enum de string, Object.values(MyEnum) retorna os valores. Para um enum numérico, o objeto também guarda as chaves reversas, então filtre: Object.values(MyEnum).filter((v) => typeof v === 'number').
Os enums estão obsoletos?
Não. Eles continuam fazendo parte do TypeScript. A opção mais nova erasableSyntaxOnly, adicionada no TypeScript 5.8, apenas permite que projetos que dependem de type stripping os proíbam, porque um enum não pode ser removido só apagando anotações.
O Node.js roda arquivos com enums diretamente?
Não com o type stripping padrão. A documentação do Node lista as declarações de enum entre os recursos que precisam de geração de código e não são suportados nesse modo, então compile-os com tsc ou outro transformador, ou troque por um objeto as const.
Enums numéricos: compactos, mas frágeis
Sem inicializadores, os membros são numerados 0, 1, 2 em ordem. Dê um valor ao primeiro, como Low = 1, e o resto continua a partir dele. O objeto gerado guarda tanto nome para número quanto número para nome.
Essa compactação também é o risco. Os números não significam nada fora do seu código, e adicionar um membro no meio renumera em silêncio tudo o que vem depois.
Enums de string: legíveis e rígidos
Todo membro precisa de um literal de string, o que torna os valores autoexplicativos em logs, URLs e JSON. A rigidez funciona para os dois lados: um valor lido de uma API é uma string, não o enum, então você ainda precisa de uma verificação antes de tratá-lo como tal.
O padrão as const
Um objeto literal marcado com as const mantém os valores exatos de string como tipos. Combine com type Role = (typeof Role)[keyof typeof Role] e você tem um objeto em tempo de execução para iterar, mais um tipo união que aceita tanto Role.Admin quanto o literal admin.
Isso é JavaScript simples com anotações, então qualquer removedor de tipos lida com ele, e nada extra é gerado além do objeto que você escreveu.
Os três tipos de enum e o que geram
Enum numérico com valor inicial
Mid e High continuam contando a partir de Low. O objeto gerado mapeia nas duas direções.
Enum de string
Cada membro é atribuído uma vez, sem entrada reversa.
const enum
A declaração desaparece e cada uso vira o seu valor.
Alternativas apagáveis
Objeto as const mais uma união derivada
Funciona com removedores de tipos, itera com Object.values e aceita a string pura.
União simples quando não é preciso uma lista em tempo de execução
Apagada por completo; o compilador ainda rejeita qualquer outra string.
Proibir enums em um projeto com type stripping
Com esta opção, uma declaração de enum é um erro de compilação.
Enum numérico
Enum de string
const enum
Objeto as const
Tipo união
Gerador de enum
Nome do tipo
Membros (separados por vírgula)
Primeiro número
Estilo de enum
TypeScript
JavaScript gerado
Copiar TypeScript
Copiar JavaScript
Use nomes que comecem com uma letra, $ ou _, e que tenham só letras, dígitos, $ ou _, sem repetir nenhum nome.