TypeScript é JavaScript com um sistema de tipos estáticos por cima. Todo programa JavaScript é sintaxe TypeScript válida; o TypeScript acrescenta anotações de tipo, um compilador que as verifica antes de o código rodar e um passo de build que as remove de novo. Em tempo de execução só existe JavaScript, então toda a diferença está no que você descobre antes de publicar.
Em JavaScript, a mesma função é esse código sem type Product = ..., : Product[] e : number. Os tipos acrescentam informação para o compilador e para o editor; eles não mudam o que o programa faz.
TypeScript vs JavaScript em resumo
| JavaScript | TypeScript | |
|---|---|---|
| Sistema de tipos | Dinâmico: os tipos pertencem aos valores e só são conhecidos em tempo de execução | Estático: os tipos são declarados ou inferidos e verificados em tempo de compilação |
| Quando aparecem os erros de tipo | Quando a linha roda (undefined, NaN, TypeError) | No editor enquanto você digita, e ao compilar |
| Onde roda | Navegadores, Node.js, Deno, Bun, diretamente | Nos mesmos lugares, depois que os tipos são removidos |
| Passo de build | Nenhum | tsc ou um bundler, ou um runtime que remove os tipos sozinho |
| Arquivos | .js, .mjs, .cjs | .ts, .mts, .cts, .tsx, mais declarações de tipo .d.ts |
| Velocidade em execução | Referência | Idêntica: a saída é JavaScript |
| Suporte do editor | Autocompletar a partir de tipos inferidos e das tipagens das bibliotecas, que podem ser incompletas | Autocompletar, renomear e "find all references" a partir dos tipos declarados |
| Curva de aprendizado | Menor | JavaScript mais o sistema de tipos |
| Padrão | ECMAScript, pelo TC39 | Um projeto open source da Microsoft que acompanha o ECMAScript |
O mesmo código nas duas linguagens
Aqui está uma função em JavaScript. Nada nela diz como user deve ser:
function greeting(user) {
return `Hello, ${user.firstName} ${user.lastName}`;
}
greeting({ firstname: "Ada", lastName: "Lovelace" });
// "Hello, undefined Lovelace", no error anywhere
A versão em TypeScript declara o formato uma vez, e o erro de digitação é apontado antes de o código rodar:
interface User {
firstName: string;
lastName: string;
}
function greeting(user: User): string {
return `Hello, ${user.firstName} ${user.lastName}`;
}
greeting({ firstname: "Ada", lastName: "Lovelace" });
// error TS2561: Object literal may only specify known properties,
// but 'firstname' does not exist in type 'User'. Did you mean to write 'firstName'?
As anotações são toda a diferença de sintaxe. O TypeScript também acrescenta algumas declarações próprias (interface, type, enum, generics como Array<string>, modificadores de acesso como private), mas as instruções, os operadores e os objetos nativos são os do JavaScript.
O que o TypeScript pega e o JavaScript não
O JavaScript converte tipos em silêncio. Este bug é comum com valores vindos de campos de formulário, que são sempre strings. Rode para ver o que o compilador diz:
index.ts(7,17): error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'number[]'.
Type 'string' is not assignable to type 'number'.
Em JavaScript isso roda e imprime 010205, porque 0 + "10" é concatenação de strings. O TypeScript se recusa a compilar até as strings serem convertidas, por exemplo com fromForm.map(Number).
A outra grande categoria são valores que podem faltar. Array.prototype.find retorna undefined quando nada corresponde, e o TypeScript obriga você a tratar isso:
index.ts(8,13): error TS18048: 'user' is possibly 'undefined'.
A versão em JavaScript puro quebra em tempo de execução com TypeError: Cannot read properties of undefined (reading 'name'). A correção em TypeScript é tratar o caso que o compilador apontou:
Saída:
GRACE
no user with id 3
O que o TypeScript não pega: erros de lógica (uma fórmula errada tem o tipo certo) e qualquer coisa sobre dados que entram no programa em tempo de execução. Uma resposta de API tipada como User só é tão correta quanto o servidor que a enviou, porque os tipos somem quando o código roda. Verifique esses dados com código de tempo de execução.
Usando bibliotecas JavaScript no TypeScript
Todo pacote npm funciona a partir do TypeScript, porque a saída é JavaScript de qualquer forma. Os tipos de um pacote vêm de um destes três lugares:
- O próprio pacote traz arquivos
.d.ts. A maioria dos pacotes mantidos ativamente traz, e você não instala nada a mais. - Um pacote
@typesseparado do projeto comunitário DefinitelyTyped:npm install --save-dev @types/lodashadiciona os tipos dolodash. - De lugar nenhum. Nesse caso, com
strictligado, o próprio import é um erro:
error TS7016: Could not find a declaration file for module 'lodash'. '/project/node_modules/lodash/lodash.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/lodash` if it exists or add a new declaration (.d.ts) file containing `declare module 'lodash';`
A solução é instalar o pacote @types se existir, ou descrever o módulo você mesmo em um arquivo .d.ts; a página sobre arquivos de declaração mostra como.
O passo de build
Navegadores e Node.js não verificam tipos, então o TypeScript precisa de um passo entre o seu código-fonte e o código que roda. Há três configurações comuns:
- O
tsccompila tudo. Ele verifica os tipos e grava arquivos.js, geralmente em uma pastadist. Simples, e o padrão para bibliotecas. - Um bundler ou servidor de desenvolvimento remove os tipos, e o
tsc --noEmitos verifica. Vite e esbuild removem tipos sem verificar, o que mantém os recarregamentos rápidos; o editor e uma etapa de CI rodam o verificador de tipos. - O runtime remove os tipos. As versões atuais do Node.js, o Deno e o Bun rodam arquivos
.tsdiretamente. Nenhum deles verifica tipos ao rodar, então otsc --noEmit(oudeno check) continua sendo o jeito de encontrar erros de tipo.
O JavaScript não precisa de nada disso, e essa é a maior vantagem prática dele para scripts pequenos. O custo do passo do TypeScript é principalmente a configuração, um tsconfig.json e uma dependência de desenvolvimento typescript, e o tempo de compilação; o compilador nativo do TypeScript 7 reduziu esse tempo em cerca de dez vezes em projetos grandes.
Curva de aprendizado
Tudo o que você sabe de JavaScript continua valendo, porque o runtime do TypeScript é JavaScript. O conteúdo novo é o sistema de tipos, e ele vem em camadas:
- Anotações em variáveis, parâmetros e valores de retorno (
: string,: number[]). - Tipos de objeto com
interfaceetype, propriedades opcionais, unions comostring | number. - Narrowing: verificar um valor com
typeof,inou===para que o compilador saiba em qual caso você está. - Generics, utility types como
Partial<T>ePick<T, K>, e tipos avançados para autores de bibliotecas.
As duas primeiras camadas cobrem a maior parte do código de aplicações. Boa parte da tipagem é inferida, então muito código TypeScript parece JavaScript com anotações só nas assinaturas das funções.
Quando escolher TypeScript ou JavaScript
TypeScript é melhor que JavaScript? Para código mantido por várias pessoas ou que vive por anos, normalmente sim, e o mercado foi nessa direção: pela contagem de contribuidores mensais do GitHub, o TypeScript passou o JavaScript e o Python em agosto de 2025 e se tornou a linguagem mais usada no GitHub. Para scripts pequenos, JavaScript puro costuma ser a ferramenta melhor.
Escolha TypeScript quando:
- Mais de uma pessoa trabalha no código, ou ele será mantido por meses ou anos.
- A base de código é grande o bastante para você não conseguir guardar todas as assinaturas de função na cabeça.
- Você faz refactoring com frequência: renomear uma propriedade atualiza todos os usos, e o compilador lista o que sobrou.
- Você publica uma biblioteca: os arquivos
.d.tsdão autocompletar e verificações a quem a usa. - O framework espera isso. Apps Angular são escritos em TypeScript, Next.js e Astro criam projetos novos em TypeScript por padrão, e os templates de React, Vue e Svelte do Vite têm cada um uma variante em TypeScript.
Escolha JavaScript quando:
- O programa é um script curto, um experimento pontual ou um trecho de código no console do navegador.
- Você está aprendendo a programar pela primeira vez e quer menos conceitos de uma vez.
- Não há passo de build e você não quer ter um. Mesmo assim,
// @ts-checkcom JSDoc dá alguma verificação em um arquivo.jspuro.
Migrando um projeto JavaScript para TypeScript
A migração não precisa acontecer de uma vez. O compilador aceita JavaScript ao lado de TypeScript:
{
"compilerOptions": {
"allowJs": true,
"checkJs": false,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}
Com allowJs, arquivos .js compilam e podem importar de arquivos .ts, e o contrário também. Depois converta aos poucos:
- Renomeie um arquivo de
.jspara.tse corrija os erros que o compilador apontar nele. - Comece pelas folhas (módulos utilitários com poucos imports) e vá avançando para dentro.
- Ligue o
checkJs, ou adicione// @ts-checkno topo de arquivos.jsespecíficos, para verificar os tipos dos arquivos que você ainda não renomeou.
Em arquivos JavaScript verificados, comentários JSDoc fornecem os tipos:
// @ts-check
/**
* @param {number} price
* @param {number} qty
* @returns {number}
*/
function lineTotal(price, qty) {
return price * qty;
}
lineTotal("3", 2);
// error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
Alguns times param por aí: arquivos JavaScript com tipos em JSDoc, verificados pelo tsc, e nenhum passo de build para o próprio código. Outros vão até o .ts. Se você ligar o strict em um projeto existente, espere muitos erros no início; a página sobre strict mode lista o que cada flag verifica para você ativá-las uma por vez.
Perguntas frequentes
Qual é a principal diferença entre TypeScript e JavaScript?
O TypeScript adiciona tipos estáticos ao JavaScript. Você descreve o que cada valor é (name: string, items: Item[]) e o compilador do TypeScript aponta erros antes de o código rodar. O JavaScript não verifica nada antes: um tipo errado só aparece quando aquela linha executa, muitas vezes como undefined ou um TypeError.
TypeScript é melhor que JavaScript?
Para a maioria dos projetos mantidos por mais de uma pessoa, ou que duram mais do que algumas semanas, sim: os tipos pegam classes inteiras de bugs, tornam o refactoring seguro e alimentam o autocompletar do editor. Para um script curto, um protótipo rápido ou um exercício de aprendizado, JavaScript puro é mais rápido de começar e não precisa de configuração de build.
TypeScript é mais rápido que JavaScript?
Não, e também não é mais lento. O TypeScript compila para JavaScript e os tipos são apagados, então o código que roda é o mesmo JavaScript que você escreveria à mão. O único custo extra é o tempo de compilação durante o desenvolvimento.
Devo aprender JavaScript ou TypeScript primeiro?
Aprenda o básico de JavaScript primeiro ou junto com o TypeScript. Todo o comportamento em tempo de execução (variáveis, funções, objetos, arrays, promises) é JavaScript, e o TypeScript só o descreve. Quando você consegue escrever programas pequenos em JavaScript, acrescentar tipos é um passo curto.
Posso usar TypeScript e JavaScript no mesmo projeto?
Sim. Defina "allowJs": true no tsconfig.json e o compilador aceita arquivos .js ao lado dos .ts. Adicione "checkJs": true (ou um comentário // @ts-check por arquivo) para verificar os tipos dos arquivos JavaScript também, usando tipos de comentários JSDoc. É o jeito usual de migrar um projeto arquivo por arquivo.