Serta Apps

Pesquisar
Close this search box.

Um tutorial de TypeScript passo a passo para novatos

Você provavelmente já ouviu falar do TypeScript — a linguagem criada e mantida pela Microsoft que teve um grande impacto na Internet, com muitas tarefas pendentes adotando e migrando seu código para o TypeScript. TypeScript é um superconjunto tipado de JavaScript. Em outras palavras, ele fornece variações para JavaScript — e, portanto, o título. No entanto, por que você precisaria dessas variedades? Que vantagens eles criam? E você deve reescrever sua base de código completa para colher os benefícios deles? Essas perguntas e outras serão respondidas neste tutorial do TypeScript para alunos.

Assumimos uma informação primária de JavaScript e suas ferramentas, mas nenhuma informação prévia de TypeScript é necessária para observar ao lado.

Algum código JavaScript impreciso

Para começar, vamos dar uma olhada em algum código JavaScript simples bastante comum que você pode encontrar em qualquer base de código. Ele busca algumas fotos da API do Pexels e as insere no DOM.

No entanto, este código tem vários erros de digitação que vão desencadear problemas. Veja se você pode identificá-los:

const PEXELS_API_KEY = '...';

async operate fetchImages(searchTerm, perPage) {
  const end result = await fetch(`https://api.pexels.com/v1/search?question=${searchTerm}&per_page=${perPage}`, {
    headers: {
      Authorization: PEXELS_API_KEY,
    }
  });
  const information = await end result.json();

  const imagesContainer = doc.qerySelector('#images-container');
  for (const picture of information.pictures) {
    const img = doc.createElement('picture');
    img.src = picture.src.medium;
    imagesContainer.append(img);
  }
}

fetchImages('canines', 5);
fetchImages(5, 'cats');
fetchImages('puppies');

Você pode ver os problemas dentro da instância acima? Na verdade, caso você execute esse código em um navegador, você obterá erros instantaneamente; no entanto, ao aproveitar ao máximo o TypeScript, obteremos os erros mais rapidamente, fazendo com que o TypeScript localize esses pontos em nosso editor.

Encurtar esse ciclo de sugestões é eficaz – e será mais útil à medida que a escala do seu desafio aumenta. É simples identificar erros nesses 30 traços de código, mas e se você estiver trabalhando em uma base de código com 1000 traços? Você veria algum ponto em potencial simplesmente então?

Observação: não é necessário obter uma chave de API do Pexels para acompanhar este tutorial do TypeScript. No entanto, se você preferir executar o código, um segredo de API é totalmente gratuito: basta ingressar em uma conta e, em seguida, criar uma.

Trabalhando TypeScript do Editor

Antigamente, o TypeScript exigia que cada informação fosse escrita como .tsinformação. No entanto, hoje em dia, a rampa de integração é mais suave. Você não quer que um arquivo TypeScript seja escrito em código TypeScript: como substituto, executaremos TypeScript em qualquer arquivo JavaScript que desejarmos!

Quando você é um usuário do VS Code (não entre em pânico caso não seja – nós iremos até você!), isso pode funcionar no campo sem mais necessidades. Permitiremos a verificação do TypeScript incluindo isso no topo do nosso arquivo JavaScript (é vital que seja a linha principal):


Você deve então obter alguns erros carmesim ondulados em seu editor que destacam nossos erros, conforme ilustrado abaixo.

TypeScript mostrando erros no VS Code

Você também precisa ver uma cruz no canto esquerdo traseiro com um dois ao lado. Clicar nele pode revelar os problemas que foram percebidos.

Erros exibidos no console do VS Code

E só porque você não está no VS Code não significa que você não poderá obter a mesma experiência com os erros de destaque do TypeScript. A maioria dos editores hoje usa o Language Server Protocol (também conhecido como LSP), que é o que o VS Code usa para alimentar sua integração com o TypeScript.

Vale a pena pesquisar on-line para encontrar seu editor e os plug-ins úteis para organizá-lo.

Colocando e trabalhando o TypeScript regionalmente

Quando você não está no VS Code, caso contrário, gostaria de uma resposta normal, você pode até executar o TypeScript na linha de comando. Nesta parte, apresentarei caminhos.

Primeiro, vamos gerar um novo desafio. Esta etapa pressupõe que você tenha o Node e o npm instalados em sua máquina :

mkdir typescript-demo
cd typescript demo
npm init -y

Em seguida, adicione TypeScript ao seu desafio:

npm set up --save-dev typescript

Observação: você pode configurar o TypeScript globalmente em sua máquina, mas eu gosto de instalá-lo por projeto. Dessa forma, garanto que controlei exatamente qual modelo de TypeScript cada desafio usa. Isso é útil, você provavelmente tem um desafio que não toca há algum tempo; você pode continuar usando um modelo TS mais antigo nesse desafio, enquanto tem um desafio mais moderado usando um modelo mais moderno.

Assim que for inserido, você poderá executar o compilador TypeScript ( tsc) para obter os mesmos erros (não se preocupe com esses outros sinalizadores, pois falaremos mais sobre eles em breve):

npx tsc index.js --allowJs --noEmit --target es2015
index.js:13:36 - error TS2551: Property 'qerySelector' doesn't exist on sort 'Doc'. Did you imply 'querySelector'?

13   const imagesContainer = doc.qerySelector('#images-container');
                                      ~~~~~~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:11261:5
    11261     querySelector<Okay extends keyof HTMLElementTagNameMap>(selectors: Okay): HTMLElementTagNameMap[K] | null;
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    'querySelector' is asserted right here.

index.js:16:9 - error TS2339: Property 'src' doesn't exist on sort 'HTMLElement'.

16     img.src = picture.src.medium;
           ~~~

Discovered 2 errors.

Você poderá ver que o TypeScript na linha de comando destaca os erros de código JavaScript idênticos que o VS Code destacou na captura de tela acima.

Corrigindo os erros em nosso código JavaScript

Agora que temos o TypeScript instalado e funcionando, vamos dar uma olhada em como veremos e depois corrigir os erros que o TypeScript está sinalizando.

Vamos verificar nosso primeiro erro.

A propriedade qerySelectornão existe na classificaçãoDoc

index.js:13:36 - error TS2551: Property 'qerySelector' doesn't exist on sort 'Doc'. Did you imply 'querySelector'?

13   const imagesContainer = doc.qerySelector('#images-container');

  node_modules/typescript/lib/lib.dom.d.ts:11261:5
    11261     querySelector<Okay extends keyof HTMLElementTagNameMap>(selectors: Okay): HTMLElementTagNameMap[K] | null;
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    'querySelector' is asserted right here.

Isso pode parecer bastante complicado caso você não esteja acostumado a estudar os erros do TypeScript, portanto, não entre em pânico se parecer um pouco estranho! O TypeScript notou que, on-line 13, nos referimos como uma técnica doc.qerySelector. Queríamos dizer, doc.querySelectorno entanto, cometeu um erro ao digitar. Teríamos descoberto isso quando tentamos executar nosso código no navegador, mas o TypeScript está pronto para nos alertar sobre isso mais cedo.

Na metade seguinte, ele destaca lib.dom.d.tse a querySelector<Okay...>operação está mergulhando no código TypeScript mais avançado, então não se preocupe com isso, mas, em um nível alto, é o TypeScript nos mostrando que sabe que existe um método chamado , querySelectore suspeita nós precisaríamos disso.

Vamos agora ampliar a parte final da mensagem de erro acima:

index.js:13:36 - error TS2551: Property 'qerySelector' doesn't exist on sort 'Doc'. Did you imply 'querySelector'?

Particularmente, preciso dar uma olhada no conteúdo textual didn't exist on sort 'Doc'. No TypeScript (e amplamente em cada linguagem tipada), os objetos têm o que é chamado de arquivo sort.

No TypeScript, números como 1ou 2.5têm o tipo quantity, strings como "howdy world"têm o tipo stringe uma ocasião de um componente HTML tem o tipo HTMLElement. Isso é o que permite ao compilador do TypeScript testar se nosso código está correto. Uma vez que ele está ciente do tipo de uma coisa, ele está ciente de quais recursos você pode nomear que levam aquela coisa, ou quais estratégias existem nela.

Observação: se você quiser aprender mais sobre variedades de informações, consulte o guia “ Introdução às classificações de informações: estáticas, dinâmicas, robustas e fracas ”.

Em nosso código, o TypeScript viu que nos referimos a doc. Isso pode ser uma variável mundial dentro do navegador, e o TypeScript está ciente disso e está ciente de que tem o tipo de arquivo Doc. Essa papelada gentil (no caso de você perdoar o trocadilho!) Todas as estratégias que citaremos. Esta é a razão pela qual o TypeScript sabe que querySelectoré uma técnica e que o erro ortográfico qerySelectornão é.

Veremos mais desses tipos conforme passamos por outros tutoriais do TypeScript , mas é daí que vem todo o poder do TypeScript. Descreveremos rapidamente nossas variedades pessoais, o que significa que, na verdade, prolongaremos o sistema de classificação para obter informações sobre todo o nosso código e o que faremos ou não com qualquer objeto explícito em nossa base de código.

Agora vamos voltar nossa atenção para nosso erro subseqüente, que é um pouco menos claro.

A propriedade srcnão existe na classificaçãoHTMLElement

index.js:16:9 - error TS2339: Property 'src' doesn't exist on sort 'HTMLElement'.

16     img.src = picture.src.medium;

Esse é um tipo de erro onde geralmente é necessário olhar um pouco acima do erro para encontrar o problema. Todos nós sabemos que um fator de imagem HTML tem um srcatributo, então por que o TypeScript não tem?

const img = doc.createElement('picture');
img.src = picture.src.medium;

O erro aqui está na primeira linha: depois de criar um novo fator de imagem, é necessário nomeá-lo doc.createElement('img')(porque a tag HTML é <img>, não <picture>). Assim que tentamos isso, o erro desaparece, porque o TypeScript está ciente disso, uma vez que você nomeia doc.createElement('img'), você obtém novamente um componente que possui uma srcpropriedade. E isso é tudo até as variedades .

Enquanto você nomeia doc.createElement('div'), a coisa retornada é do tipo HTMLDivElement. Enquanto você nomeia doc.createElement('img'), a coisa retornada é semelhante HTMLImageElement. HTMLImageElementtem uma srcpropriedade declarada nele, então o TypeScript está ciente de que você poderá nomear img.src. No entanto HTMLDivElement, não, então o TypeScript apresentará erros.

No caso de doc.createElement('picture'), porque o TypeScript não descobre nenhum elemento HTML com a tag picture, ele retornaria um objeto de classificação HTMLElement(um elemento HTML genérico, não específico de pelo menos uma tag), que também não possui a srcpropriedade .

Assim que repararmos esses dois erros e executarmos novamente o TypeScript, você verá que não obtivemos nada novamente, o que mostra que não houve erros. Quando você configurou seu editor para indicar erros, esperamos que nenhum seja exibido.

Como você pode configurar o TypeScript

É um pouco trabalhoso adicionar // @ts-checka cada arquivo, e quando executamos o comando no terminal para adicionar esses outros sinalizadores. O TypeScript permite que você, em vez disso, o permita em um desafio de JavaScript criando um jsconfig.jsonarquivo.

Crie jsconfig.jsondentro da listagem raiz do nosso desafio e coloque isso dentro dela:

{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "goal": "es2015"
  },
  "embrace": ["*.js"]
}

Isso configura o compilador TypeScript (e a integração TS do seu editor) para:

  1. Examine as informações do JavaScript (a checkJspossibilidade).
  2. Suponha que estamos construindo em uma atmosfera ES2015 (a goalpossibilidade). Padronizar para ES2015 significa que usaremos problemas como garantias sem que o TypeScript nos dê erros.
  3. Não produza nenhuma informação compilada (a noEmitpossibilidade). Enquanto estiver escrevendo o código TypeScript nas informações de fornecimento do TypeScript, você deseja que o compilador gere o código JavaScript para que você possa executá-lo no navegador. Como estamos escrevendo o código JavaScript que opera no navegador, não queremos que o compilador gere nenhuma informação para nós.
  4. Por fim, embrace: ["*.js"]instrui o TypeScript a examinar qualquer arquivo JavaScript na listagem raiz.

Agora que temos este arquivo, você poderá substituir sua instrução de linha de comando por esta:

npx tsc -p jsconfig.json

Isso pode executar o compilador com nosso arquivo de configuração ( -paqui é a abreviação de “desafio”), para que você não precise cruzar todos esses sinalizadores ao operar o TypeScript.

Trabalhando em modo estrito

Agora que estamos aqui, vamos ver como tornaremos o TypeScript muito mais completo ao verificar nosso código. O TypeScript suporta algo chamado “modo estrito”, que instrui o TypeScript a testar nosso código mais completamente e garantir que lidamos com quaisquer possíveis ocasiões em que, por exemplo, um objeto pode ser undefined. Para tornar isso mais claro, vamos ligá-lo e ver quais erros obtemos. Adicione "strict": truea "compilerOptions"uma parte de e jsconfig.json, em seguida, execute novamente o TypeScript na linha de comando.

Enquanto você faz uma alteração no jsconfig.jsonarquivo, pode descobrir que precisa reiniciar o editor para que ele selecione essas modificações. Portanto, caso você não esteja vendo os mesmos erros que eu, experimente.

npx tsc -p jsconfig.json
index.js:3:28 - error TS7006: Parameter 'searchTerm' implicitly has an 'any' sort.

3 async operate fetchImages(searchTerm, perPage) {
                             ~~~~~~~~~~

index.js:3:40 - error TS7006: Parameter 'perPage' implicitly has an 'any' sort.

3 async operate fetchImages(searchTerm, perPage) {
                                         ~~~~~~~

index.js:15:5 - error TS2531: Object is probably 'null'.

15     imagesContainer.append(img);
       ~~~~~~~~~~~~~~~

Discovered 3 errors.

Vamos começar com o erro final primeiro e estão disponíveis novamente para os outros:

index.js:15:5 - error TS2531: Object is probably 'null'.

15     imagesContainer.append(img);
       ~~~~~~~~~~~~~~~

E vamos dar uma olhada em como imagesContaineré delineado:

const imagesContainer = doc.querySelector('#images-container');

Ativar o strictmodo tornou o TypeScript mais rigoroso em garantir que os valores com os quais contamos existam. Neste caso, não é garantido que doc.querySelector('#images-container')realmente retornará um componente; e se não for descoberto? doc.querySelectorretornará nullse um componente não for descoberto e agora habilitamos o modo estrito, o TypeScript está nos dizendo que imagesContainerpode ser realmente null.

Classificações de União

Antes de ativar o modo estrito, o tipo imagesContainerera Component, mas agora ativamos o modo estrito, o tipo imagesContaineré Component | null. O |operador (pipe) cria variedades de união – que você aprenderá como “ou” – então aqui imagesContaineré de tipo Componentou null. Quando o TypeScript nos diz Object is probably 'null', é exatamente isso que está nos dizendo e quer que tenhamos certeza de que a coisa existe antes de usá-la.

Vamos corrigir isso lançando um erro caso não descubramos o fator de contêiner de fotos:

const imagesContainer = doc.querySelector('#images-container');
if (imagesContainer === null) {
  throw new Error('Couldn't discover images-container factor.')
}

for (const picture of information.pictures) {
  const img = doc.createElement('img');
  img.src = picture.src.medium;
  imagesContainer.append(img);
}

O TypeScript agora está satisfeito; lidamos com o nullcaso lançando um erro. O TypeScript é sábio o suficiente para entender agora que, se nosso código não gerar um erro na terceira linha do trecho acima, imagesContainernão é null, e devido a esse fato deve existir e deve ser do tipo Component.

Seu tipo era Component | null, mas quando era, nullpoderíamos ter gerado um erro, então agora deveria ser Component. Esse desempenho é chamado de redução de classificação e é uma ideia realmente útil para se prestar atenção.

implícito qualquer

Agora vamos mudar nossa consideração para os dois erros restantes que temos:

index.js:3:28 - error TS7006: Parameter 'searchTerm' implicitly has an 'any' sort.

3 async operate fetchImages(searchTerm, perPage) {
                             ~~~~~~~~~~

index.js:3:40 - error TS7006: Parameter 'perPage' implicitly has an 'any' sort.

3 async operate fetchImages(searchTerm, perPage) {

Uma das muitas implicações de ativar o modo estrito é que ele ativa uma regra conhecida como noImplicitAny. Por padrão, quando o TypeScript não conhece o tipo de uma coisa, o padrão é fornecer uma classificação específica do TypeScript chamada any. anynão é um tipo bom de se ter em seu código, porque não há nenhum guia relacionado a ele por meio do que o compilador testará. Vai permitir que algo ocorra.

Prefiro imaginá-lo porque o compilador levanta os braços no ar e diz “Não posso ajudar aqui!” A utilização anydesativa qualquer verificação de classificação útil para essa variável individual, por isso recomendo fortemente evitá-la.

Descrever a assinatura de operação com JSDoc

Os 2 erros acima são TypeScript nos dizendo que não informamos quais são as variedades das 2 variáveis ​​que nossa operação usa e que as está padronizando novamente para any. A boa notícia é que fornecer essas informações ao TypeScript significava reescrever seu arquivo no código TypeScript ;

Por exemplo, aqui está como apresentaremos as informações de classificação para nossa fetchImagesoperação:


async operate fetchImages(searchTerm, perPage) {
  
}

Todos os comentários JSDoc devem começar com /**(palavra o adicional *no início) e dentro deles usamos tags específicas, começando com @, para indicar as propriedades de classificação. Aqui declaramos dois parâmetros ( @param), e depois colocamos sua classificação entre chaves (idênticos aos objetos JavaScript comuns).

Aqui deixamos claro que searchTermé a stringe perPageé uma quantidade. Enquanto estamos nisso, também usamos @returnpara declarar o que essa operação retorna. No nosso caso, não retorna nada, e a classificação que usamos no TypeScript para declarar isso é void.

Vamos agora executar novamente o compilador e ver o que ele diz:

npx tsc -p jsconfig.json
index.js:30:13 - error TS2345: Argument of sort 'quantity' isn't assignable to parameter of sort 'string'.

30 fetchImages(5, 'cats')
               ~

index.js:31:1 - error TS2554: Anticipated 2 arguments, however obtained 1.

31 fetchImages('puppies')
   ~~~~~~~~~~~~~~~~~~~~~~

  index.js:9:40
    9 async operate fetchImages(searchTerm, perPage) {
                                             ~~~~~~~
    An argument for 'perPage' was not supplied.

Discovered 2 errors.

Essa é a coisa fantástica sobre o TypeScript. Dando mais informações ao compilador, ele provavelmente agora detectará erros em como estamos chamando o código que não poderia antes. Neste caso, são descobertas duas chamadas para fetchImageso local onde obtivemos os argumentos dentro da ordem falaciosa, e a segunda para o local onde esquecemos o perPageargumento (nenhum dos dois searchTerm, perPagesão parâmetros eletivos).

Vamos simplesmente excluir essas chamadas, no entanto, espero que ajude a mostrar a facilidade do compilador e as vantagens de fornecer ao compilador mais informações de classificação.

Declarando classificações de informações usando uma interface

Embora não seja sinalizado pelo compilador, uma preocupação que nosso código tem está nesta linha:

const information = await end result.json();

O problema aqui é que o tipo de retorno await end result.json()é any. É porque, uma vez que você pega uma resposta da API e a converte em JSON, o TypeScript não tem noção de quais informações estão lá, então o padrão é any. No entanto, como todos sabemos o que a API Pexels retorna, podemos fornecer algumas informações de classificação por meio do uso de interfaces TypeScript . Isso nos permite informar o TypeScript em relação à forma de um objeto: quais propriedades ele possui e quais valores essas propriedades possuem.

Vamos declarar uma interface — mais uma vez, utilizando a sintaxe JSDoc, que representa as informações retornadas da API do Pexels. Usei a referência da API Pexels para determinar quais informações são retornadas. Neste caso, vamos realmente delinear duas interfaces: uma irá declarar a forma de um single pictureque a API Pexels retorna, e a outra irá declarar a forma geral da resposta da API.

Para delinear essas interfaces usando JSDoc, usamos @typedef, que nos permite declarar variedades mais avançadas. Em seguida, usamos @propertypara declarar propriedades únicas nessa interface. Por exemplo, aqui está o tipo que eu crio para uma pessoa Picture. As classificações devem sempre começar com uma letra maiúscula.

Se você preferir ver uma referência completa de todo o desempenho JSDoc suportado, o site do TypeScript tem uma lista completa com exemplos .


Esse tipo diz que qualquer objeto digitado como a Picturepode ter uma propriedade, src, que é um objeto com três propriedades de string: medium, massivee thumbnail. Você descobrirá que a API Pexels retorna mais; você não precisa declarar cada propriedade que um objeto possui caso não precise, mas apenas o subconjunto que deseja. Aqui, nosso aplicativo atualmente usa apenas a mediumimagem, mas declarei alguns outros tamanhos que precisaríamos mais cedo ou mais tarde.

Agora que temos esse sort, vamos declarar o sort PexelsSearchResponse, que pode caracterizar o que obtemos novamente da API:


Esse é o lugar onde você poderá ver o valor de declarar suas variedades pessoais; nós declaramos que este objeto tem uma propriedade, picturese então declaramos que seu valor é uma matriz, onde cada mercadoria é desse tipo Picture. Isso é o que a Array<X>sintaxe denota: é uma matriz onde cada mercadoria dentro da matriz é de tipo X. [1, 2, 3]poderia ser um Array<quantity>, por exemplo.

Assim que conseguirmos isso, usaremos a @sortobservação JSDoc para informar ao TypeScript que as informações que obtemos novamente end result.json()são do tipo PexelsSearchResponse:


const information = await end result.json();

@sortnão é algo que você deva obter regularmente. Normalmente, você precisa que o compilador resolva de forma inteligente o tipo de problema, razoavelmente do que deve informá-lo sem rodeios. Mas, como resultado de end result.json()return any, podemos substituir isso por nossa classificação.

Dê uma olhada se todo o lote está funcionando

Para mostrar que isso está funcionando, escrevi errado intencionalmente mediumao referenciar o URL da imagem:

for (const picture of information.pictures) {
  const img = doc.createElement('img');
  img.src = picture.src.mediun; 
  imagesContainer.append(img);
}

Se executarmos o TypeScript mais uma vez, veremos o problema que o TypeScript não teria notado se não tivéssemos conseguido o trabalho que simplesmente fizemos para declarar a interface:

index.js:35:25 - error TS2551: Property 'mediun' doesn't exist on sort '{ medium: string; massive: string; thumbnail: string; }'. Did you imply 'medium'?

35     img.src = picture.src.mediun;
                           ~~~~~~

  index.js:18:18
    18    * @property {{medium: string, massive: string, thumbnail: string}} src
                        ~~~~~~
    'medium' is asserted right here.

Discovered 1 error.

Conclusão

O TypeScript tem muito a oferecer aos construtores envolvidos em bases de código sofisticadas. Sua capacidade de encurtar o ciclo de sugestões e apresentar erros antes que seja necessário recompilar e carregar o navegador é basicamente útil. Vimos como ele pode ser usado em qualquer desafio JavaScript atual (evitando a necessidade de reescrever seu código em .tsinformações) e como é fácil começar.

Espero que você tenha gostado deste tutorial do TypeScript para alunos. No restante desta coleção de tutoriais em três partes, que pode ser acessada no SitePoint Premium , começaremos a colocar esses dados em ação e apresentar métodos para construir um software do mundo real a partir do zero, utilizando TypeScript que aproveita ao máximo o ecossistema TypeScript. Isso pode evitar problemas como a renderização dinâmica de marcações e o uso de uma API de terceiros, permitindo que os usuários busquem fotos ou filmes e os marquem como favoritos e armazenem esses favoritos em armazenamento nativo.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

0

Rolar para cima