Seu Primeiro Componente usando TypeScript

Ricardo Pedroni
RPEDRONI
Published in
11 min readMar 1, 2021

Ganhe confiança no seu código e integridade de tipos — enquanto aumenta sua empregabilidade.

Fala, galera! Aqui é o Professor Ricardo Pedroni e vamos juntos para mais uma aula fantástica 🎉
🎥 Não esqueça de ver essa aula e muitas outras no nosso Canal do YouTube!

Se tem um aspecto que considero “o próximo passo” para um desenvolvedor React tornar-se mais competente na sua arte de criar e desenhar interfaces modernas e robustas é saber usar TypeScript.

“Mas professor, me falaram que preciso entender tudo sobre ordenação de árvores binárias, ponderadas usando listas quadruplamente encadeadas usando assembly rodando num PIC de 4bits para progredir minha carreira como desenvolvedor!”. E isso é verdade, num lindo mundo de entrevistas de quadro branco e nos sonhos dos puristas de ciências da computação 🦄

Você tem 2 minutos para explicar o Jantar dos Filósofos. Se você passar no teste, segunda-feira começa a trabalhar, trocando cores de botões em CSS.

Se você tem contato com empresas que trabalham de verdade com React e fazem seus testes com problemas reais do mundo real, uma forma de mostrar sua competência e cuidado com sua arte é justamente você elevar a qualidade com qual você produz essa arte. E o TypeScript é uma excelente forma de fazer isso.

Nessa aula, não vou entrar em detalhes muito técnicos do que o TypeScript (TS) é capaz de fazer (e acreditem, é capaz de fazer muita coisa) mas vamos molhar nossos pés um pouco porque eu vejo que tem MUITO desenvolvedor com medo da ferramenta quando a verdade é que o TS só é tão intimidador quanto você quer que ele seja.

Parecido com outras bibliotecas de tipificação do JavaScript (como o flow), a adaptação do TS pode ser gradual ou por inteiro — você decide. Então na aula de hoje vamos seguir por esse caminho gradual, onde vamos usar o TS para elevar a qualidade do nosso código, de uma forma simples, modular e por passos, justamente para entendermos algumas das capacidades maravilhosas que ele proporciona — e que você finalmente perca o medo dele, como você venceu o seu medo de palhaços aos 23 anos de idade.

Oi, sou o Palhaço Bolhas! Sou seu amigo e vim comer sua alma.

O que é TypeScript?

Longe de termos uma aula sobre o que é em detalhes e quais são todos os poderes do TS, a resposta resumida é a seguinte: TypeScript é JavaScript tipificado. Isso é, TS é JS com a possibilidade de definir tipos, trazendo mais robustez e segurança ao seu código e, convenhamos, a coisa mais massa de TypeScript: auto-completar.

Como o o TS é um superconjunto do JS (i.e. todo e qualquer código JS é código TS válido), absolutamente tudo que você pode fazer em JS, pode fazer igual em TS. Por isso que usar TypeScript pode ser um processo gradual, indo componente por componente, arquivo por arquivo, sem a necessidade de transformar o projeto todo em uma só sentada.

Criando seu Projeto TypeScript com o Create React App

Nosso foco vai ser no uso do TS. Dito isso, não quero perder muito tempo com instalações complicadas e configurações avançadas (o TS suporta bastante configuração). Para termos um projeto React funcional com TS da maneira mais rápida, vamos alavancar nosso amigável Create React App (CRA), que já temo suporte (semi-)nativo ao TS. Para criar um novo projeto com TS, basta rodar:

npx create-react-app my-ts-comp-project --template typescript
# Ou com o yarn
yarn create react-app my-ts-comp-project --template typescript

O npx e o yarn create são ferramentas “one-off” de criação e configuração de projetos — i.e. é uma forma de usar um pacote npm sem ter que instalar ele localmente

Uma vez rodado, teremos um projeto CRA normal mas com suporte a usar TS logo de cara. A primeira coisa que você vai reparar de diferente é que vão haver vários arquivos .ts e .tsx invés dos .js e .jsx que talvez esteja acostumado. Por mais que não seja obrigatório usar a extensão para denotar arquivos TS, é um costume para diferenciar de arquivos que sejam puramente escritos em JS.

Outra coisa que talvez note é um novo arquivo na raiz do projeto, o tal do .tsconfig. Basicamente esse arquivo define e configura como deseja que o TS funcione para esse projeto. Para projeto diferentes, é normal haver .tsconfigs diferentes, justamente denotando as diferenças e preferências do projeto e dos desenvolvedores nele trabalhando.

Para provar que o TypeScript interpreta JavaScript normalmente, troque a extensão do arquivo App.tsx para App.jsx (atualize também a inclusão desse arquivo no index.tsx para import App from './App.jsx para puxar o arquivo correto). Recarregue a página e ~boom~, nada mudou (não esqueça de mudar de .jsx de volta .tsx quando terminar).

Repare também por último que por mais que estamos num projeto TypeScript, os arquivos que o React gera são idênticos em conteúdo do que os de um projeto JS normal. O CRA não está usando TS para nada, e é nosso papel adicionar agora esses super poderes 🦸‍♀️

React e o TypeScript

TypeScript pode e é usado muito em qualquer ambiente JavaScript — React sendo um desses ambiente, é natural querer usar ele aqui também. Uma das principais maneiras de usar TS com o React é justamente na definição das APIs de componentes React — no caso de componentes, a “interface” que eles tem com o mundo é justamente o props , então nada melhor do que começar a adicionar TS aos nossos componentes do que aqui.

▶️ Nosso objetivo nesse momento não é fazer o componente funcionar “de verdade” mas, sim, vermos como podemos usar o TS para elevar a qualidade dos nossos componentes.

Vamos criar nosso componente, o NumberInput, para demonstrar o TS em ação. As funcionalidades que queremos do nosso componente de teste são:

  1. O componente é uma entrada (input) de números inteiros;
  2. O componente tem dois parâmetros, min e max , que controlam os limites de valor de entrada. A entrada só pode estar na faixa [min , max];
  3. O componente pode receber um valor inicial, e esse valor deve ser forçado a estar entre os valores de min e max;
  4. O componente também aceita um placeholder, uma string opcional que serve de placeholder no input;
  5. Ao ter um valor válido inserido, o componente deve sinalizar ao componente pai que o seu valor mudou, passando o valor atual válido ao mesmo.

Nada muito complicado para começarmos. Então bora começar a ver nosso pequeno exemplo ganhando vida 🍀

Bem radical né? Pois bem, precisamos começar de algum lugar. Vamos então começar a preparar o componente justamente com os valores que ele pode receber do mundo externo, nosso amigo props .

Props Tipados

Para isso, vamos definir em TS quais são esses os nomes desses props, e os tipos a eles associados:

A palavra type significa “tipo” (pikachu_suprise_face.jpg), e está criando nesse exemplo um “tipo” para nós — o tipo NumberInputProps . O TS nos permite criar tipos indefinidamente complexos, com tipos extendendo e herdando de outros tipos, com a possibilidades de implementar interfaces e muitas outras coisas. Mas o curioso que no React, pelo menos quando o assunto é componentes, raramente precisamos de algo muito complexo, nos limitando a simplesmente definir os tipos dos parâmetros que esperamos do mundo externo. Só com isso, já vamos ver bastante mágica acontecer ✨

Adicione esse tipo para os props do seu componente:

E falando em mágica… sua aplicação talvez magicamente “crasheou”. Na verdade, o TS gerou um erro de compilação (transpilação na verdade, mas vamos ignorar isso por enquanto) e seu app deu erro. Mas antes que você fique puto que o TS está gerando um erro, saiba: ISSO É BOM!

Óia lá, tá faltando coisa.

Erro bom? Erro bom! O erro está acontecendo justamente porque você está usando o componente de forma errada. Afinal, você falou que os props do componente são min, max, initialValue e placeholder mas você não está fornecendo nenhum deles no momento. Então que ótimo que o TS está sendo seu amigo e te avisando isso logo de cara — o JS não teria essa capacidade. Para resolvermos isso, vamos adicionar valores de props no uso do nosso componente

Resolvido, né? Não, continuamos a fazer cagada um erro de programação. Lembra que quando definimos nossos props no componente, falamos que todos os valores eram do tipo number, significando que esperamos os três valores como número mas estamos invés passando strings. Ou seja, mais uma vez o TS nos salvando de erros simples mas que podem demorar muito para debugar.

Corrigindo, temos agora:

E nosso app volta a funcionar 🎉

Uma coisa que você pode ter reparado é que na nossa especificação, nós falamos que o componente pode receber um valor inicial mas não que necessariamente vai receber um valor. No TS, podemos traduzir isso para um valor opcional, anotando o tipo desse campo como opcional, usando ? depois do nome da variável, tendo assim:

Sendo assim, experimenta tirar o initialValue do <NumberInput /> e verá que o TS não vai reclamar mais. Espertinho. Inclusive, se agora dentro do nosso componente fizermos a soma de todos os props numéricos, teremos um problema:

Note que por mais que os três valores são números, o TS vai reclamar que somar o valor de initialValue ao min e max pode dar ruim, visto que agora o initialValue pode ser indefinido. Mesmo que você forneça um valor aos a todos os props, o erro do TS não vai sumir porque ele previne os erros em tempo de compilação e não depuração — a ideia é previnir erros e não descobrir eles apenas quando acontecerem. Caso quiser resolver isso, basta dar um valor default ao initialValue e o TS também será inteligente de saber que agora sempre haverá um valor válido:

Quanto à lista de props, está faltando um último prop, justamente para sinalizarmos ao componente pai que um valor válido foi inserido no input. De forma clássica, usaremos um callback para fazer essa sinalização:

TS também é capaz de anotar os tipos em uma função, indicando quais são os parâmetros e qual o valor de retorno. Nesse caso, nossa callback passa um único número e retorna nada (eis o void ali). Vale comentar que os tipos que o TypeScript pode representar são muitos e suas complexidades variam desde valores primitivos (string, number, boolean, etc.) até objetos complexos, unions, range de valores e template literal types . Como nosso objetivo hoje é fazer apenas uma introdução, vamos ao segundo local clássico onde TS pode nos ajudar e muito em React: estado.

Estado Tipado

props são apenas uma parte de um componente — muito componentes dependem de manter estado para poderem funcionar, e isso se aplica no nosso caso. A forma de adicionar TS para nos ajudar com state no React é usando-o nas chamadas ao useState

Parte da mágica do TS é que ele consegue muitas vezes inferir tipos baseado apenas que usamos, como é o caso aqui. Deixa seu mouse em cima do value e veja o que o TS conseguiu descobrir sobre ele:

No caso de useState o TS atribui o tipo da variável baseado no valor que é passado como valor inicial do estado, nesse caso puxando o tipo do initialValue, ou seja, number. Mas o que aconteceria se não houvesse um valor inicial ou esse valor inicial fosse indefinido? Bora lá ver:

Como você poderia imaginar, ele definiu o tipo de value como undefined, justamente porque o valor realmente é indefinido. Inclusive, se tentarmos usar o setValue em seguida no código, o TS reclamaria caso a função recebesse qualquer valor que não fosse undefined

Se encontrar um caso assim e quiser sinalizar ao TS o tipo que deseja à sua variável de estado, muitas funções aceitam um tipo genérico que pode ser usado internamente para definir o tipo de outros valores, nesse caso no a variável de retorno da função. Veja só:

Basicamente estamos falando ao TS o seguinte:

“Saca só typescript, confia em mim , o tipo dessa variável É number e essa tal de função setValue vai receber um number como entrada quando eu usar ela, firmeza? abs irmão vlw falow me liga no zap.” Desenvolvedor, 2021

Inclusive, ao tentar usar o setValue com outro valor que não seja um número, ele vai te proteger mais uma vez:

Se você for atento, na verdade vai ver que o TS é mais inteligente ainda — por mais que falamos que o value e o setValue é e recebe um number, repare que o TS está falando que esse valor na verdade é number | undefined, significando que pode ser número mas também pode ser indefinido e ele está correto — quando inicializamos nossa variável, ela realmente é indefinida e nem prestamos muita atenção a isso — então alavanque esse poder todo a seu favor.

Tipo Assim

Por mais que isso foi uma introdução ligeiraça de TypeScript, espero que tenha te motivado a incluí-lo na sua próxima aventura programática ou o seu projeto JavaScript puro. Dá para começar a ver que as vantagens em termos de robustez, leitura de código, manutenibilidade e debug dos componentes e que sua adoção pode ser gradual e por partes. Então está esperando o que? Vá lá tipificar tudo isso aí 💪

Espero que esse post tenha te ajudado!
Ficou com dúvida ou quer mandar uma real? Deixa nos comentários!
Ah, e me acompanhe também no YouTube: https://bit.ly/3q0TIAU ✌!

TLDR;

  • Empresas sérias estão cada vez buscando mais devs que entendam e usam TypeScript (TS) para trazer robustez e segurança aos seus apps;
  • TS é um superconjunto do JavaScript — tudo que vale em JS vai valer em TS;
  • O Create React App pode ser criado para ter um suporte nativo ao TS;
  • Uma das principais formas de usar TS com React é a definição dos props de um componente e a tipificação do estado desse componente;
  • TS te dá suporte a auto-complete, segurança de tipos e robustez de código;
  • Testes são mais fáceis de escrever por causa da garantia de tipos.

--

--

Ricardo Pedroni
RPEDRONI

O Professor Ricardo Pedroni ensina conceitos importantes e boas práticas de desenvolvimento de projetos em software. YouTube https://bit.ly/3q0TIAU