O bug que o JavaScript deixa passar
Um erro de digitação bobo, invisível até o exato momento em que o código quebra. É esse tipo de bug que o TypeScript existe para evitar.
Estudar esta lição interativa →Se você já programou em JavaScript por um tempo, provavelmente já passou por isto: o código roda sem reclamar, tudo parece certo, e do nada uma tela mostra Cannot read properties of undefined. Você caça o erro, e descobre que foi um erro de digitação bobo, uma propriedade escrita errada em algum lugar do código, que ninguém percebeu até o programa tentar usá-la de verdade.
Rode o exemplo abaixo. Repare que a primeira chamada funciona bem, e a segunda quebra, mesmo sendo um código muito parecido:
// JavaScript puro: nada aqui impede um erro de digitação.
function boasVindas(usuario) {
return "Olá, " + usuario.nome.toUpperCase() + "!";
}
console.log(boasVindas({ nome: "Ana" }));
console.log(boasVindas({ nomee: "Bruno" })); // "nomee", não "nome": passou despercebidoJavaScript puro. Rode e leia o erro no console.
O problema está na segunda chamada: { nomee: "Bruno" }, com um "e" a mais. O objeto não tem uma propriedade nome, então usuario.nome vale undefined, e chamar .toUpperCase() em undefined derruba o programa. O pior detalhe é quando você descobre isso: só quando aquela linha específica roda. Se ela estivesse escondida atrás de um clique raro, esse bug podia ficar dias, semanas, até chegar para um usuário de verdade em produção.
Pense no JavaScript como um funcionário extremamente obediente, mas sem nenhum senso crítico: ele faz exatamente o que você mandou, palavra por palavra, mesmo que a instrução não faça sentido. Se você errar uma palavra na receita, ele só percebe o problema na hora de usar o ingrediente errado, no meio do preparo, não antes.
O TypeScript é uma extensão do JavaScript que adiciona uma coisa que falta nele: a possibilidade de descrever o formato esperado de um valor, e um verificador que confere, antes de qualquer linha rodar, se todo o código respeita esses formatos. Veja o mesmo exemplo, agora com uma pequena anotação de tipo no parâmetro da função. Não se preocupe em entender toda a sintaxe ainda, é cedo para isso. Só rode e observe o quadro que aparece abaixo do editor, antes mesmo de você clicar em Rodar:
// Mesmo código, mas o parâmetro agora tem um formato esperado.
// Não se preocupe em entender toda a sintaxe ainda: só observe
// o diagnóstico aparecer abaixo do editor antes mesmo de rodar.
function boasVindas(usuario: { nome: string }) {
return "Olá, " + usuario.nome.toUpperCase() + "!";
}
console.log(boasVindas({ nome: "Ana" }));
console.log(boasVindas({ nomee: "Bruno" })); // agora o TypeScript avisaObserve o quadro de diagnóstico logo abaixo do editor.
Essa caixa que apareceu é o diagnóstico de tipo: o TypeScript releu o seu código, comparou cada valor com o formato esperado e encontrou uma inconsistência, exatamente na linha do nomee. Ele não esperou você rodar nada, muito menos um usuário clicar em algo em produção. Essa é a virada de chave deste curso inteiro: erros que no JavaScript só aparecem em tempo de execução (rodando o código, às vezes só em certos caminhos) passam a aparecer em tempo de checagem (só de escrever, antes de rodar, em todos os caminhos que o compilador consegue analisar).
Um detalhe prático: os diagnósticos do TypeScript vêm em inglês, sempre com um código (como TS2561) que ajuda a pesquisar o erro. O quadro do exemplo mostra um deles. Com cinco códigos e seus significados você já entende a maioria do que vai aparecer neste curso:
| Código | O que o TypeScript diz (em inglês) | Em português |
|---|---|---|
TS2322 | Type 'string' is not assignable to type 'number' | O tipo texto não cabe onde se espera número. |
TS2345 | Argument of type … is not assignable to parameter of type … | O valor passado na chamada não tem o formato que o parâmetro pede. |
TS2339 | Property 'b' does not exist on type … | Essa propriedade não existe nesse tipo (cuidado com erro de digitação). |
TS2561 e TS2353 | Object literal may only specify known properties | O objeto tem uma propriedade que o tipo não conhece. O TS2561 ainda sugere o nome certo ("Did you mean …?"). |
TS18048 | 'x' is possibly 'undefined' | x pode estar sem valor neste ponto: confira antes de usar. |
Os cinco diagnósticos mais comuns do curso, traduzidos. Ler a mensagem inteira, de cima a baixo, quase sempre dá a pista da correção.
Sempre que uma célula de código tiver a etiqueta TS no canto (em vez de JS), ela está sendo checada de verdade pelo TypeScript enquanto você digita, com um pequeno atraso (uma fração de segundo) entre parar de digitar e o diagnóstico atualizar. Se aparecer a mensagem "Carregando checagem de tipos...", é só aguardar um instante: o motor completo de tipos ainda está sendo baixado.
Um detalhe importante: mesmo com o diagnóstico vermelho na tela, o botão Rodar ainda executa o código (o TypeScript "confia" em você e deixa passar, avisando). Quem trava de verdade a entrega do código em um projeto real é o processo de build do time, não o editor. Aqui no curso, o hábito que queremos construir é outro: tratar o diagnóstico como um sinal para parar e corrigir antes de seguir em frente, exatamente como faria um time profissional.
// Sua vez! Este código tem o mesmo erro de digitação de antes.
// O parâmetro já está tipado. Encontre o "nomee" errado e troque
// para "nome" até o diagnóstico de tipo desaparecer.
function apresentar(pessoa: { nome: string }) {
return "Esta é " + pessoa.nome;
}
console.log(apresentar({ nomee: "Carla" }));Corrija o typo até o diagnóstico sumir.