DEV Community

Pedro Santos
Pedro Santos

Posted on

Builder de tipagem dinâmica com fluent api no typescript

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!

Image description

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:

Image description

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:

Image description

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

Image description

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

Image description

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:

Image description

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.

Image description

Por fim, teremos uma função construir() que retornará a nossa casa com a tipagem atual.

Image description

Nossa classe ficou da seguinte forma:

Image description

Agora, é possível criar de forma dinâmica nossa casa. Para criar uma casa apenas com piscina podemos facilmente criar adicionando a piscina:

Image description

Ou para criar com quartos, banheiros e um quintal faremos da seguinte forma:

Image description

Além disso, ao passar o mouse em cima do objeto já sabemos exatamente o que tem dentro da casa:

Image description

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)