TypeScript: Enumeração do TypeScript (enum)
Última atualização: 2026-08-26
As enums são um dos poucos recursos de tipos do TypeScript que apresentam comportamento em tempo de execução — elas são tanto um tipo quanto geram objetos reais em JavaScript.
1. Enumeração numérica
(1) Sintaxe básica
enum Direction {
Up, // 0(Auto-increment from 0)
Down, // 1
Left, // 2
Right // 3
}
let dir: Direction = Direction.Up;
console.log(dir); // 0
console.log(Direction[0]); // "Up"(Inverse Mapping)
(2) Valores iniciais personalizados
enum Status {
Active = 1, // 1
Inactive, // 2(Auto-increment)
Pending // 3
}
enum HttpStatus {
OK = 200,
Moved = 301,
BadRequest = 400,
NotFound = 404,
ServerError = 500
}
let code: HttpStatus = HttpStatus.OK;
console.log(code); // 200
(3) Mapeamento reverso de enumerações numéricas
Após a compilação, as enumerações numéricas geram objetos de mapeamento bidirecional — é possível recuperar um valor pelo nome ou um nome pelo valor:
enum Role {
Admin = 0,
Editor = 1,
Viewer = 2
}
// Forward Mapping: name → value
console.log(Role.Admin); // 0
// Inverse Mapping: value → name
console.log(Role[0]); // "Admin"
console.log(Role[1]); // "Editor"
JavaScript gerado após a compilação:
var Role;
(function (Role) {
Role[Role["Admin"] = 0] = "Admin";
Role[Role["Editor"] = 1] = "Editor";
Role[Role["Viewer"] = 2] = "Viewer";
})(Role || (Role = {}));
2. Enumeração de strings
(1) Sintaxe básica
Cada elemento de uma enumeração de cadeias de caracteres deve ser atribuído explicitamente — não há incremento automático:
enum EventType {
Click = "click",
Change = "change",
Submit = "submit",
Focus = "focus"
}
let event: EventType = EventType.Click;
console.log(event); // "click"
(2) A enumeração de cadeias de caracteres não possui mapeamento inverso
enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
console.log(Color.Red); // "RED" ✅ Forward Mapping
// console.log(Color["RED"]); // undefined ❌ String enumeration has no reverse mapping
▶ Exemplo: Definindo status de pedidos usando uma enumeração
enum OrderStatus {
Pending = "PENDING",
Processing = "PROCESSING",
Shipped = "SHIPPED",
Delivered = "DELIVERED",
Cancelled = "CANCELLED"
}
function getStatusLabel(status: OrderStatus): string {
switch (status) {
case OrderStatus.Pending: return "Pending";
case OrderStatus.Processing: return "Processing...";
case OrderStatus.Shipped: return "Shipped";
case OrderStatus.Delivered: return "Delivered";
case OrderStatus.Cancelled: return "Canceled";
}
}
let currentStatus: OrderStatus = OrderStatus.Processing;
console.log(`Current Status:${getStatusLabel(currentStatus)}`);
console.log(`Status Code:${currentStatus}`);
Saída:
Current Status:Processing...
Status Code:PROCESSING
3. Enumerações heterogêneas
As enumerações podem conter uma mistura de valores numéricos e de cadeias de caracteres — mas isso não é recomendado:
enum Mixed {
No = 0,
Yes = "YES"
}
4. Enumerações const
const enum Substituído por uma expressão inline durante a compilação — não gera um objeto JavaScript, oferecendo melhor desempenho, mas com funcionalidade limitada:
(1) Sintaxe básica
const enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
let c = Color.Red;
// After compilation:let c = "RED"(Direct Inline Replacement,No enumeration objects)
(2) Limitações das enumerações const
const enum Direction {
Up = "UP",
Down = "DOWN"
}
// ❌ const Enumerations cannot use reverse mapping.
// console.log(Direction[0]);
// ❌ const Enumerations cannot be iterated over at runtime
// for (let d in Direction) { }
// ✅ Only simple value references are allowed.
let dir = Direction.Up; // Compile to let dir = "UP"
(3) A opção preserveConstEnums
Se você quiser que as enumerações const não sejam inlinadas, mas mantenham os objetos de enumeração, habilite preserveConstEnums: true:
// tsconfig.json
// "preserveConstEnums": true
const enum Status {
Active = 1
}
let s = Status.Active;
// After compilation:Enumeration objects are still generated(But quotes are also inlined.)
5. Tempo de execução e segurança de tipos nas enumerações
(1) Enumerações como tipos
enum Role {
Admin,
Editor,
Viewer
}
function checkAccess(role: Role): boolean {
return role === Role.Admin || role === Role.Editor;
}
checkAccess(Role.Admin); // ✅
checkAccess(0); // ✅ Numeric enumerations accept numeric values(but ⚠️ not recommended)
// checkAccess(99); // ✅ Compilation successful!Any number can be converted to——This is a numeric enumeration vulnerability.
let r: Role = 99 é um valor válido. Isso ocorre porque as enumerações numéricas foram projetadas tendo em mente os sinalizadores de bits. Se você precisar de restrições rigorosas de valores, use enumerações de string ou tipos de união literais.
(2) A enumeração de strings é mais segura
enum Role {
Admin = "ADMIN",
Editor = "EDITOR",
Viewer = "VIEWER"
}
let r: Role = Role.Admin; // ✅
// r = "ADMIN"; // ❌ String enumeration does not accept regular strings.
// r = "SUPERADMIN"; // ❌ Only enumeration members are accepted
6. Enumerações x Tipos de união literais
| Propriedade | Enumeração | Tipo de união literal |
|---|---|---|
| Código em tempo de execução | Sim (são criados objetos) | Não (tipos puros) |
| Mapeamento reverso | Enumeração digital: Sim | Não |
| Percorrer todos os valores | Sim | Não |
| Restrições de valor | Enumeração numérica (mais flexível) | Rigorosa |
| Sugestões de código | Autocompletar membros de enumeração | Autocompletar valores de união |
| Tamanho do pacote | Aumenta o tamanho do código | Tamanho zero |
| Interoperabilidade com JS | Os valores de enumeração são objetos personalizados | Strings/números nativos |
(1) Cenários para o uso de enumerações
- É necessário um mapeamento inverso (valor → nome)
- Todos os valores devem ser percorridos em tempo de execução
- As enumerações são necessárias para serem utilizadas como objetos em tempo de execução (como mapeamentos de constantes de API)
(2) Cenários que utilizam tipos de união literais (recomendados como primeira opção)
- São exigidas apenas restrições de tipo
- Requer interoperabilidade com strings e números nativos do JavaScript
- Procure obter o menor tamanho de pacote possível
- Não é necessário nenhum comportamento em tempo de execução
▶ Exemplo: Comparação dos dois métodos
// Method 1:Enumeration
enum Direction1 {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
// Method 2:Literal Union Types(Recommendations)
type Direction2 = "UP" | "DOWN" | "LEFT" | "RIGHT";
// The two are equivalent in terms of type constraints.
function move1(dir: Direction1): void { console.log(dir); }
function move2(dir: Direction2): void { console.log(dir); }
move1(Direction1.Up); // ✅ "UP"
move2("UP"); // ✅ Use the string directly,Even simpler
// But enumerations can be iterated over
console.log(Object.values(Direction1));
// ["UP", "DOWN", "LEFT", "RIGHT"]
// Literal union types cannot be iterated over(Pure compile-time types)
Saída:
// Executed successfully
▶ Exemplo: Enums const para segurança de tipos com custo zero
const enum LogLevel {
Debug = 0,
Info = 1,
Warn = 2,
Error = 3
}
function log(level: LogLevel, message: string): void {
const prefix = ["DEBUG", "INFO", "WARN", "ERROR"][level];
console.log(`[${prefix}] ${message}`);
}
log(LogLevel.Info, "Server started"); // Compiles to: log(1, "Server started")
log(LogLevel.Error, "Connection lost"); // Compiles to: log(3, "Connection lost")
Saída:
[INFO] Server started
[ERROR] Connection lost
const enum members are inlined at compile time—no enum object is emitted in the JS output, resulting in smaller bundle size.
❓ Perguntas Frequentes
P: Deve-se usar enumerações? R: A comunidade do TypeScript está dividida em dois campos — um acredita que as enumerações são uma característica distintiva do TypeScript e devem ser usadas, enquanto o outro acredita que os tipos de união literais são mais leves e mais recomendados. Conselho prático: se você precisar apenas de restrições de tipo (o que ocorre na maioria das situações), use tipos de união literais; se precisar de comportamento em tempo de execução (como iteração ou mapeamento reverso), use enumerações.
P: Por que as enumerações numéricas aceitam qualquer número? R: Essa é uma decisão de projeto do TypeScript — as enumerações numéricas suportam sinalizadores de bits (
enum Perm { Read = 1, Write = 2, Execute = 4 }), e as combinações de bitsRead | Write = 3são válidas, mas não estão incluídas na definição da enumeração. Portanto, o tipo de enumeração numérica flexibilizou suas restrições. Se você não quiser esse comportamento, use enumerações de string ou tipos de união literais.
P: Qual é a diferença entre uma enumeração
conste uma enumeração comum? R: Uma enumeraçãoconsté incorporada em tempo de compilação —Color.Redé substituída diretamente por"RED", e nenhum objeto de enumeração é gerado. A vantagem é um pacote menor e um desempenho mais rápido em tempo de execução; a desvantagem é que ela não pode ser mapeada de forma reversa, não pode ser iterada e não pode ser usada em contextos dinâmicos. Priorize o uso de enumeraçõesconst(a menos que você precise de recursos de tempo de execução).
P: As enumerações podem ser combinadas com interfaces ou aliases de tipo? R: Sim. Os valores das enumerações podem ser usados como tipos de propriedade para interfaces —
interface Config { role: Role }. Os membros das enumerações também podem ser usados como membros de tipos de união —type Mixed = Role.Admin | "superadmin". As enumerações são um conceito unificado de tipo e valor, oferecendo flexibilidade de uso.
📖 Resumo
- As enumerações numéricas são incrementadas automaticamente a partir de 0 e suportam mapeamento reverso; as enumerações de cadeia de caracteres devem ser atribuídas explicitamente e não suportam mapeamento reverso.
- Não é recomendável usar enumerações heterogêneas (que misturem números e cadeias de caracteres)
- As enumerações
constsão incorporadas em tempo de compilação, resultando em sobrecarga zero em tempo de execução, mas com funcionalidade limitada - Os tipos de enumeração numérica podem aceitar qualquer número (uma falha de projeto), enquanto as enumerações de cadeia de caracteres são mais restritivas
- Na maioria dos casos, recomenda-se usar tipos de união literais em vez de enumerações — eles são mais leves, mais seguros e não ocupam espaço algum.
- Use a enumeração apenas quando for necessário mapear valores na ordem inversa ou percorrer todos os valores.
📝 Exercícios
- Problema básico (Dificuldade ⭐): Dada uma enumeração de caracteres
Season(Primavera/Verão/Outono/Inverno), escreva uma função que retorne uma descrição do intervalo de meses correspondente com base na estação do ano. - Exercício avançado (Dificuldade ⭐⭐): Use
const enumpara definir métodos HTTP (GET/POST/PUT/DELETE) e, em seguida, defina uma interfaceRequestque inclua as propriedadesmethodeurl. Crie vários objetos de solicitação para verificar as restrições de tipo. - Desafio (Dificuldade: ⭐⭐⭐): Use tipos de união literal em vez de enumerações para implementar um “sistema de permissões”: defina
Permission = "read" | "write" | "execute" | "admin"e, em seguida, implemente a funçãohasPermission(userPerms: Permission[], required: Permission): booleanpara verificar se um usuário possui uma permissão específica (o administrador tem todas as permissões).