Enumeração em Typescript
Olá tudo bom? Se você é programador ou estudante de alguma faculdade de tecnologia que envolva algum tipo de programação orientada à objetos, você provavelmente já ouviu falar de enum. Mas afinal para que serve esse carinha?
O enum, também conhecido como Enumeração, é um tipo abstrato de dado, que possui valores atribuídos a exatamente um elemento de um conjunto finito de dados. A seguir temos alguns dos usos clássicos. Como podem ver, podemos ou atribuir um valor para cada “label”, ou apenas utilizar a label para categorizar.
O principal uso do Enumerador é categorização. Frequentemente temos algum campo chamado type que aceitará um enumerador.
Enumerador em Javascript
Apesar do intuito do post ser enums em Typescript. Acho válido apresentar as soluções desde o Javascript básico.
No exemplo acima temos três opções de enum em Javascript. Ao trabalhar com Javascript no frontend, isso atendia muito bem minhas necessidades. Sempre senti falta da sintaxe de enums que eu conhecia do Java. Era uma estrutura da linguagem apenas dedicada a essa tarefa. Em Javascript, eu estava usando um objeto pra criar o enum, o que sempre foi um pouco estranho mas, em Javacript, os tipos de dados são bem mais limitados do que em Java, o qual possui estruturas de dados para diversos tipos de situações.
O jogo virou com Typescript
Com a popularização do Typescript, muitos recursos interessantes foram adicionados à programação de Javascript. Para quem era acostumado com Java ou outra linguagem compilada, pode trazer uma parte considerável do conhecimento para utilizar no ecossistema Javascript, seja com Node.js ou para a Web.
Mas estamos aqui para falar de enum correto? E o Typescript trouxe para nós o enum. Ótimo certo? Não exatamente, veja os exemplos a seguir:
Como podem ver no gist acima, os dois primeiros casos funcionam perfeitamente. No terceiro e mais complexo, o comportamento não era o que eu esperava. Pelo menos até então, o Typescript permite apenas números e strings como valores de enums. Ou seja, Um objeto com code e desc. Não poderia ser usado como valor dos enums, desa forma, caso se queira objetos complexos como valores de enumeradores, a melhor solução é fazer como em javascript puro certo? Errado.
Nas minhas pesquisas a respeito do tema, encontrei o seguinte no StackOverflow. Usando ele como base cheguei no seguinte resultado:
Agora sim chegamos em algo realmente interessante. Para pegar a chave basta fazer: EBreeds.AKITA.toString()
. Em algum lugar do código você pode ter que validar a ação com base no enum. Por exemplo:
if(code === Breeds.AKITA.code) { //code here }
A solução acima é muito boa e muito elegante, o intelissense da sua IDE agradece. Essa solução era quase perfeita para o que eu precisava. Faltavam algumas coisas. Os seguintes pensamentos me ocorreram:
- Caso apenas o código do enum esteja salvo no banco de dados como posso reaver o objeto do meu Ebreeds, a partir do código?
- A comparação com
code === Breeds.Akita.code
não é muito interessante. Eu prefiro comparar tipos complexos de dados a comparar tipos primitivos de dados.
O seguinte código foi o resultado final do meu experimento:
Com o construtor privado, nenhuma outra classe conseguirá instanciar esses enums novamente. Além disso, criei dois métodos para comparação, um para comparar Enums e outro para validar o próprio código. Mas a parte que eu mais gostei foi o map. Usando esta estrutura, é possível pegar o item a partir da string code, sem precisar fazer um laço ou uma busca em todos os items do enum para encontrar o item desejado.
Realmente vale a pena?
A verdade é que em muitos casos isto não vai valer a pena. Você pode ser acusado de estar complicando algo que deveria ser simples. De fato, existe uma linha tênue para se decidir se é mais válido um enum complexo, ou uma tabela no banco de dados. A verdade é que São poucos os casos em que um enum tão robusto será de fato necessário.
Este artigo apresentou uma solução extremamente robusta para o uso de enums em Typescript, além de formatos mais simples e diretos. O ponto mais interessante da classe EBreeds, não é o enum em si, mas pensar como estruturas de dados podem auxiliar o trabalho do Desenvolvedor de Software. A verdade é que durante nosso dia a dia nem sempre temos tempo de criar soluções como esta que foi apresentada e, infelizmente, muitas soluções acabam por apenas usar if/else ou um for simples por não haver tempo hábil para fazer uma entrega de qualidade.
Se você é daqueles, como eu fui, que torcia o nariz para Estrutura de dados na faculdade, talvez seja uma boa dar uma segunda chance. As vezes é preciso uma certa experiência para conseguir criar os seus próprios tipos abstratos de dados, além de paciência. Também é importante que eles surjam do domínio da sua aplicação, afinal, um dos nossos maiores desafios é encontrar soluções com o maior custo benefício. Sua solução deve pensar em performance, manutenção, escalabilidade entre outros. O conhecimento em estruturas de dados é um dos maiores aliados do Engenheiro na busca de equilíbrio entre os pontos citados acima.
Espero que a leitura tenha sido de seu agrado. Muito obrigado e até o próximo artigo.