Nesse pequeno post iremos ver uma feature interessante do typescript que não vejo muitas pessoas comentando. Iremos aprender a utilizar a criação de uma tipagem dinâmica com o padrão de fluent api.
Começaremos rapidamente definindo alguns componentes para trabalhar em cima deles. A ideia aqui é construirmos casas dinamicamente. Existem casa que possuem piscina, outras não. Iremos ver como definir sua casa de acordo com o objeto que está sendo construído!
Começando com a fluent api, caso não esteja familiarizado com o padrão, trata-se de retornar a classe no retorno da função, para que seja possível encadear chamadas de funções. Abaixo um exemplo de utilização similar ao que faremos:
Agora que já estamos um pouco mais familiarizados com o padrão, vamos implementar de forma que a tipagem do nosso objeto seja atualizada dinamicamente. O objetivo é ter uma função construir
que irá retornar a casa com a tipagem correta de nossa casa.
Pra começar, primeiro precisamos de criar o tipo Casa
, que será definido pela extensão das variáveis existentes em CasaProps. A definição ficará da seguinte forma:
Caso não esteja familiarizado com a tipagem, a explicação do que fizemos é a seguinte:
a Casa
receberá um parametro T
, onde T
será derivado das variáveis ("chaves") presentes em CasaProps
(T extends keyof CasaProps
). Então, para cada K ("chave") presente em T iremos adicioná-la a definição da casa, sendo que associaremos o valor de K ("chave") com o valor de CasaPropsK.
Ainda confuso? Vamos ver o que isso representa no código, para assimilar melhor a ideia!
Agora, quando criamos uma Casa
teremos que associar a ela uma das propriedades presentes em CasaProps
Ao associarmos uma tipagem de Casa<"quartos">
a uma variável, teremos uma casa com o atributo com quartos, que o valor terá a tipagem de Quartos
que definimos em CasaProps
. A mesma coisa acontece se fizermos uma casa com piscina, seremos forçados a incluir uma piscina dentro da casa
Agora, a virada da chave acontece se dissermos que essa casa possui quartos e banheiros, fazemos isso indicando as duas variáveis com um |
. Casa<"quartos" | "banheiros">
irá nos dizer que a casa terá os dois atributos existindo dentro dela! Além disso, caso não haja algum dos atributos seremos notificados com um erro explicito dizendo quais são os atributos que estão faltando:
Agora que dominamos o conceito da tipagem dinâmica, vamos avançar para o builder. Iremos criar uma classe CasaBuilder
, que receberá um T
que estende as chaves de CasaProps
(CasaBuilder<T extends keyof CasaProps = never>
- para que em um primeiro momento não exista nenhuma chave associada ao builder setamos primeiramente como never).
Para a nossa fluent api, iremos ter um objeto privado _casa
que receberá a configuração. Para cada um dos atributos teremos uma função específica de criação, para setar cada campo. No entanto, iremos atualizar dinamicamente nossa tipagem, retornando a tipagem T | "variavel"
para cada variável que setarmos (exemplo: T | "quartos"
>. Fazendo isso, iremos atualizar a nossa tipagem com um novo atributo.
Por fim, teremos uma função construir()
que retornará a nossa casa com a tipagem atual.
Nossa classe ficou da seguinte forma:
Agora, é possível criar de forma dinâmica nossa casa. Para criar uma casa apenas com piscina podemos facilmente criar adicionando a piscina:
Ou para criar com quartos, banheiros e um quintal faremos da seguinte forma:
Além disso, ao passar o mouse em cima do objeto já sabemos exatamente o que tem dentro da casa:
Eu utilizei uma implementação similar a esta no backend do meu trabalho atual, para criar um serviço de parâmetros dinâmico. É um excelente jeito de simplificar tipagens complexas e ter mais controle e validação do que está sendo construído de forma dinâmica em tempo desenvolvimento.
Top comments (0)