TypeScript vs JavaScript: o que muda, o que o tsc gera | We.Inc
Veja TypeScript e o JavaScript em que ele é compilado lado a lado, entenda o que o type checker detecta, por que os tipos somem em runtime e quando JavaScript puro basta.
TypeScript é JavaScript mais um sistema de tipos. Você escreve JavaScript comum com anotações de tipo opcionais, e o compilador tsc as verifica e depois as remove para gerar JavaScript puro. Navegadores e Node rodam essa saída, então os tipos nunca existem em runtime. O ganho é pegar erros enquanto você edita, não ter código mais rápido.
Lado a lado
Pergunta
JavaScript
TypeScript
Roda direto no navegador?
Sim
Não, antes é compilado ou convertido para JavaScript
Quando os erros de tipo aparecem?
Quando o código roda
Enquanto você edita e quando o tsc verifica
Extensões de arquivo
.js, .mjs, .jsx
.ts, .tsx (.d.ts para declarações)
Tipos em runtime
Só valores
Nenhum, as anotações são apagadas
Precisa de etapa de build?
Opcional
Sim para verificar; um removedor de tipos ou bundler para rodar
JavaScript válido é entrada válida?
Sim
Sim, embora o checker possa apontar erros
Escolha um exemplo abaixo para ver um arquivo TypeScript ao lado do JavaScript que o tsc gerou para ele. Na maioria das vezes, a saída é o seu código com as anotações apagadas. Alguns recursos, como enums, geram código de verdade, e essa diferença importa na hora de escolher ferramentas.
Escolha um exemplo: anotações simples, uma interface, um enum, um const enum ou um erro de tipo.
Leia o código TypeScript à esquerda e o JavaScript gerado à direita.
Confira a nota abaixo de cada par para ver o que o compilador verificou e o que sobrou na saída.
Copie qualquer um dos lados para testar no seu próprio projeto.
Adicione um tsconfig.json com strict definido como true desde o primeiro dia. Ativar depois em uma base de código grande faz aparecerem centenas de erros de uma vez.
Ao migrar, renomeie um arquivo .js para .ts de cada vez. Definir allowJs permite que os dois tipos de arquivo convivam no mesmo projeto durante a transição.
Lembre que um JSON vindo do servidor não tem tipo até você verificá-lo. Uma anotação de tipo em dados buscados é uma promessa ao compilador, não uma verificação em runtime.
Use um removedor de tipos rápido (Vite, esbuild ou o type stripping do Node) para rodar o código e mantenha o tsc --noEmit como verificação separada no editor e no CI.
Perguntas frequentes
TypeScript é uma linguagem diferente de JavaScript?
É um superconjunto. Todo programa TypeScript vira JavaScript, e o TypeScript adiciona sintaxe para descrever o formato dos valores. Aprenda JavaScript primeiro; os tipos ficam por cima dele em vez de substituí-lo.
O TypeScript deixa meu site mais rápido?
Não. As anotações são removidas antes de o código rodar, então o navegador executa o mesmo JavaScript que você teria escrito à mão. Os benefícios são menos bugs chegando aos usuários e refatorações mais seguras.
O tsc se recusa a gerar o build quando há um erro de tipo?
Não por padrão. O tsc aponta o erro e ainda assim escreve o arquivo .js, o que torna possível uma migração gradual. Defina noEmitOnError se quiser que uma verificação com falha bloqueie a saída.
O Node consegue rodar arquivos .ts sem etapa de build?
Versões recentes do Node removem a sintaxe de tipos apagável e rodam o arquivo, com o type stripping ativado por padrão desde a v23.6.0 e a v22.18.0. O Node não verifica tipos, e sintaxes que precisam de código gerado, como enums, são rejeitadas.
Quando JavaScript puro é a melhor escolha?
Scripts pequenos, protótipos rápidos e páginas com poucas linhas de interatividade raramente compensam a configuração. Quando um projeto tem vários arquivos, várias pessoas ou dados passando entre módulos, o checker começa a economizar tempo de verdade.
O que o tsc faz de verdade
O compilador tem duas funções que as pessoas costumam confundir. Primeiro ele verifica os tipos: lê cada arquivo, descobre o tipo de cada valor e aponta tudo o que não se encaixa. Depois ele gera a saída: escreve JavaScript sem a sintaxe de tipos e, se você pedir, reescreve sintaxe mais nova para alvos mais antigos.
Toolchains modernas geralmente separam essas funções. Um bundler como o Vite remove os tipos rapidamente sem verificar nada, e o tsc --noEmit roda a verificação completa à parte, no editor ou no CI. Se você só rodar o bundler, erros de tipo podem ir para produção.
Os tipos são apagados, então valide os dados reais
Como as anotações desaparecem, o TypeScript não consegue impedir que um servidor envie uma string onde você declarou um número. Escrever const user: User = await res.json() só diz ao checker para confiar em você.
Nas bordas do seu programa, como entradas de formulário, respostas de fetch e local storage, verifique o valor em runtime com uma pequena função de guarda ou uma biblioteca de schema, e deixe o checker levar essa garantia para dentro.
Recursos que não são simplesmente apagados
Enums, namespaces com código, parameter properties e aliases import = produzem JavaScript próprio. O TypeScript 5.8 adicionou a opção erasableSyntaxOnly, que aponta erro para esses recursos, para que um arquivo funcione com removedores de tipos que só apagam anotações.
Se você pretende rodar arquivos .ts direto no Node ou com outro removedor de tipos, prefira uniões de literais de string e objetos as const em vez de enums. O guia de enums deste site mostra os dois lado a lado.
Adicionar TypeScript a um projeto JavaScript
Instalar e criar um tsconfig
Instala o compilador localmente, escreve um tsconfig.json inicial e roda uma verificação sem gerar arquivos.
allowJs permite que arquivos .js antigos fiquem ao lado de arquivos .ts novos durante uma migração; noEmit deixa a saída por conta do seu bundler.
Verificando dados que o compilador não enxerga
Uma guarda em runtime que estreita o tipo
A função verifica o valor de verdade, e o tipo de retorno informa ao compilador o que ela provou.
Anotações
Os tipos do parâmetro e do retorno são verificados e depois apagados. O corpo não é alterado.
Interface
Uma interface não gera saída nenhuma. Ela existe só para o checker.
Enum
Um enum comum vira um objeto real com mapeamento reverso, então isto é código gerado, não sintaxe apagada.
const enum
O tsc substitui os membros de const enum pelos números diretamente e deixa um comentário com o nome original.
Erro de tipo
O tsc aponta: Argument of type 'string' is not assignable to parameter of type 'number'. Ele ainda escreve o arquivo, a menos que noEmitOnError esteja definido.
TypeScript e o JavaScript em que ele se transforma