Introdução: Por que seu enum pode "vazar" e como evitar isso
Imagine que você está trabalhando em um grande projeto em JavaScript. Você criou um enum para os status do pedido: PENDING, SHIPPED, DELIVERED. Tudo funciona perfeitamente, até que em um dos módulos, algum desenvolvedor (ou você mesmo, seis meses depois) acidentalmente escreve: OrderStatus.PENDING = 'CANCELLED'. Ou, pior ainda, Object.assign(OrderStatus, { NEW_STATUS: 'hacked' }). Bum! A lógica da aplicação quebra, o bug vai para produção, e você passa uma noite sem dormir depurando.
Este é um problema clássico que acumulou milhares de visualizações no Stack Overflow. A pergunta "How can I guarantee that my enums definition doesn't change in JavaScript?" atormenta muitos. E não é à toa: JavaScript é uma linguagem dinâmica, e seus objetos são mutáveis por padrão. Mas há uma saída, e hoje vamos analisar todas as formas de proteger suas enumerações de forma confiável.
Neste artigo, mostrarei várias abordagens comprovadas: desde o simples Object.freeze() até técnicas avançadas com Symbol e TypeScript. Você aprenderá a escrever enums imutáveis que resistirão a qualquer alteração acidental (ou não).
O problema: por que enum em JavaScript é apenas um objeto
Ao contrário de algumas linguagens (C#, Java, Rust), JavaScript não possui uma construção nativa enum. Os desenvolvedores os emulam usando objetos simples:
const OrderStatus = { PENDING: 'pending', SHIPPED: 'shipped', DELIVERED: 'delivered'};Isso funciona, mas essa emulação tem uma falha fatal: qualquer um pode alterar o valor. E não se trata apenas de má intenção — muitas vezes acontece acidentalmente:
- Atribuição acidental em um loop ou callback.
- Imutabilidade? Esqueceu — e alguém estendeu o objeto.
- Bibliotecas que podem mutar objetos passados a elas.
O problema é agravado pelo fato de que, em bases de código grandes, é difícil rastrear essas alterações. É por isso que a questão de proteger enum contra alterações é tão popular.
Solução nº 1: Object.freeze() — seu primeiro escudo
A maneira mais simples e comum é usar Object.freeze(). Este método torna o objeto imutável: você não poderá adicionar, remover ou alterar propriedades.
Como funciona
const OrderStatus = Object.freeze({ PENDING: 'pending', SHIPPED: 'shipped', DELIVERED: 'delivered'});
// Tentativa de alterar — não funcionaráOrderStatus.PENDING = 'CANCELLED'; // Silêncio (no modo estrito — erro)OrderStatus.NEW = 'new'; // Não será adicionadodelete OrderStatus.SHIPPED; // Não será removido
console.log(OrderStatus.PENDING); // 'pending' — o valor não mudouPor que isso é útil? Object.freeze() funciona no nível do próprio objeto. É um mecanismo embutido que não requer bibliotecas adicionais. É ideal para proteger enum em JavaScript contra mutações acidentais.
Limitações do Object.freeze()
- Congelamento superficial — se os valores do enum forem objetos, eles permanecem mutáveis.
- Não protege contra reatribuição — se você usar
letem vez deconst, a variável pode ser sobrescrita por completo. - Não gera erros no modo não estrito — as alterações são simplesmente ignoradas, o que pode ocultar um bug.
Mas para enums simples, isso é mais do que suficiente. Se você precisar de proteção adicional, continue lendo.
Solução nº 2: Use const + Object.freeze() para bloqueio total
A combinação de const (protege contra reatribuição da variável) e Object.freeze() (protege contra