Tenha brio com sistemas de tipos
Tags: typescript, tutorial, programming, showdev
Published: 2022-07-21 03:05:55


![Brio](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xg1td1qd1umfbatvcgxb.jpeg)


## Brio ?

Brio é uma palavra sensacional e deveriamos utilizar ela mais vezes, eu só estudei o que eu estudei de sistema de tipos por causa do brio que eu tenho por esse tipo de conteúdo(parsers, compilers e afins)

Eu vi esses dias esse seguinte código e como uma pessoa com brio eu li até entender e hoje posso explicar nem que seja um pouco sobre sistemas de tipos 

![JSON parser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o577397lugailn8pj7ol.png)
 
Gist desse código está [aqui](https://github.com/type-challenges/type-challenges/issues/6999)

## O que é um sistema de tipos ?

Um sistema de tipos como a nossa wikipedia nos ajuda a dizer é:

`é um conjunto de regras que atribuem uma propriedade chamada de tipo para as várias construções`

Mas o que isso quer dizer no fim do dia ? É as regras que devemos seguir, como colocar pesos em nossas pernas igual do rock lee (sim, vai nós ajudar, confia)


![Rocklee](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xp5i734tpqbpqydn45xl.jpeg)

Quando vamos trabalhar em code bases mais maduras com códigos que possuem tipos bem definidos, temos a certeza junto aos testes que esse código funciona como deveria. Tipos ajudam a fazer a análise estática do seu código. 

Hoje iremos falar como brincar e torturar o sistema de tipos do TypeScript e de quebra aprender mais sobre como programar melhor e as bases no geral das linguagens de programação.

## TypeScript

Antes de falar de código, vou comentar por cima onde está o typechecker e algumas curiosidades sobre esse módulo do sistema do TS.

O TypeChecker tem 2.67MB e fica nessa [url](https://github.com/microsoft/TypeScript/blob/main/src/compiler/checker.ts) e ele é capaz de algumas coisas sensacionais. As melhores imagens que podem explicar o que ele pode fazer são essas


![TS Checker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pafum9mbrleivue060kf.jpeg)

### Camadas

A imagem abaixo é um panorama de como o TypeScript funciona de baixo dos panos e é essencial para se saber o que eles está fazendo antes de gerar o código JS que é lido pelo navegador


![Layers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p23mq39xrttkyh5nv3gq.jpeg)


Essas imagens veem desse [repo](https://github.com/microsoft/TypeScript-Compiler-Notes) da microsoft

## Gists

Quem me segue no twitter sabe que eu faço muito código em type-level. Geralmente fica nos gists do github [aqui](https://gist.github.com/Grubba27) Hoje vou analisar um que é relativamente simples mas muito bonito, que é um parser de HTML que eu implantei e se fosse fazer a nível de código normal ele possivelmente ficará muito parecido.

Ele segue abaixo e a partir dai irei comentar como que se cria código em TypeLevel

![HTML Parser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ilclbkxmb0vgk4lky5n8.png)
 

Parece muito código mas brio e com calma podemos chegar em algum lugar, em palavras humanas o que esse código faz ? 

```ts
  Text extends `${infer L}${infer R}`  
```

Pegue Text e divida em 2 pedaços L e R, na primeira iteração da uma palavra como Charizard L será C e R será harizard, e assim por diante, funciona em arrays também.

Extends dessa maneira precisa de um ? e de um : caso o valor seja truthy ele ria continuar o fluxo, caso não quer dizer que acabou o objeto que você está tentando dividir. Você tem que ter um fallback quando isso acontece.

### Extends ?

A palavra extends no sistema de tipos é usada para além de criar variáveis é usada como sinônimo de verificador de igualdade. No código acima usamos ele dessa forma:

```ts
 L extends '<' // Em ts normal poderia ser L === '<' ? ... : ... ou apenas if (L === '<') {...}
```

Até agora já percebemos algumas coisas, o sistema de tipos é focado em funções puras, ou seja, eu só trabalho com o que eu recebo de inputs e nada de side effects.

Além de podermos fazer if's, criar variáveis, precisamos de loops para podermos criar qualquer coisa na linguagem.

Temos isso e esse é o ponto onde eu gosto de pensar que nós como programadores preguiçosos que somos geralmente esquecemos. 

## Recursão

A maneira mais simples de se iterar algo, é por recursão. No sistemas de tipos podemos conseguir isso através de chamar o type de novo ao invés de retornar ele. no exemplo acima eu fiz isso todas as vezes e criei side effects apenas na hora de chamar a recursão de novo.

```ts
// Você passa texto simples aqui e ele irá só parar quando ver outro <

type ContentParser
  <Text extends string, Result extends string = ''> =
  Text extends `${infer L}${infer R}`
    ? L extends '<'
      ? Result
      : ContentParser<R, `${Result}${L}` >
    : never
```

A pergunta é como que ele cria esse texto que ele retorna, toda vez que eu itero pelo tipo eu vou concatenando o texto de Result até chegar em um momento que ele não precisa mais e eu retorno ele.

Consigo obter o mesmo resultado com essa função abaixo:

```ts
type ContentParser
  <Text extends string, Result extends string = ''> =
  Text extends `${infer L}${infer R}`
    ? L extends '<'
      ? Result
      : ContentParser<R, `${Result}${L}` >
    : never

const biggerThanRemover = (text: string, res: string = ''): string => {
  const [l, ...r] = text.split('');
  if (l === '<') {
    return res;
  }
  return biggerThanRemover(r.join(''), `${res}${l}`);
}
const charizard: ContentParser<'charizard<'> = biggerThanRemover('charizard<') as  'charizard'
console.log(charizard) // charizard
```

Sim esse simples código é que precisa para se criar um loop e eu particularmente acho muito mais elegando que um for loop clássico, a melhor parte é que é uma função pura, ou seja, muito fácil de ser testada e usada.

## Isso me faz um programador melhor ?

Sim, ter mais armas em seu arsenal irá te fazer mais capaz de lidar com situações adversas e poderá a partir dai dizer o que vale ou não a pena em certos cénarios.

Saber fazer um loop com recursão é algo que eu hoje digo que aprendi com total certeza depois de brincar bastante com o sistema de tipos e sem esse tempo não seria possível. 

Aprender algo que mesmo que por brincadeira e brio irá te ajudar a aprender coisas e chegar em certos limites que antes não eram realizáveis.

## Conclusão

Por fim deixo um exemplo prático que aprendi, fazer a seus colegas devs terem a melhor devXP(famosa devUX) é essencial, com mensagens de erro personalizadas conforme o erro dos tipos pode ser algo que venha a ajudar seus colegas a ficarem mais produtivos.

Segue abaixo um código que eu considero ser o mais puro ouro que se pode encontrar pela internet [link do post que eu achei](https://niksa-fantela.com/posts/typescript-custom-error-messages-with-conditional-types/):

![Custom Error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qzb67n5k5v64r0qm3wkl.png)
 

Além de ele dar sintax highlight de erro, você pode argumentar o que está de errado com um texto mais explicativo que o simples x is not assignable to type y.

Aproveite e faça bom uso do mesmo :D

## Referências

Gostaria de adicionar algumas referências que fazem útil ou que são legais de conhecer:

* [Matt Pocock](https://twitter.com/mpocock1?s=21&t=D1ne0FedC6X1YYHSVlJAoQ)
* [Structural typing](https://www.youtube.com/watch?v=MbZoQlmQaWQ)
* [TypeGame](https://github.com/fc01/TypeGame)