Menu

TypeScript vs JavaScript: diferenças com exemplos

TypeScript é JavaScript com um sistema de tipos estáticos verificado antes de o código rodar. Compare os dois lado a lado: sintaxe, o que o verificador de tipos pega, o passo de build, desempenho, curva de aprendizado e como migrar um projeto JavaScript.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

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

JavaScriptTypeScript
Sistema de tiposDinâmico: os tipos pertencem aos valores e só são conhecidos em tempo de execuçãoEstático: os tipos são declarados ou inferidos e verificados em tempo de compilação
Quando aparecem os erros de tipoQuando a linha roda (undefined, NaN, TypeError)No editor enquanto você digita, e ao compilar
Onde rodaNavegadores, Node.js, Deno, Bun, diretamenteNos mesmos lugares, depois que os tipos são removidos
Passo de buildNenhumtsc 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çãoReferênciaIdêntica: a saída é JavaScript
Suporte do editorAutocompletar a partir de tipos inferidos e das tipagens das bibliotecas, que podem ser incompletasAutocompletar, renomear e "find all references" a partir dos tipos declarados
Curva de aprendizadoMenorJavaScript mais o sistema de tipos
PadrãoECMAScript, pelo TC39Um 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 @types separado do projeto comunitário DefinitelyTyped: npm install --save-dev @types/lodash adiciona os tipos do lodash.
  • De lugar nenhum. Nesse caso, com strict ligado, 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 tsc compila tudo. Ele verifica os tipos e grava arquivos .js, geralmente em uma pasta dist. Simples, e o padrão para bibliotecas.
  • Um bundler ou servidor de desenvolvimento remove os tipos, e o tsc --noEmit os 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 .ts diretamente. Nenhum deles verifica tipos ao rodar, então o tsc --noEmit (ou deno 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:

  1. Anotações em variáveis, parâmetros e valores de retorno (: string, : number[]).
  2. Tipos de objeto com interface e type, propriedades opcionais, unions como string | number.
  3. Narrowing: verificar um valor com typeof, in ou === para que o compilador saiba em qual caso você está.
  4. Generics, utility types como Partial<T> e Pick<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.ts dã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-check com JSDoc dá alguma verificação em um arquivo .js puro.

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:

  1. Renomeie um arquivo de .js para .ts e corrija os erros que o compilador apontar nele.
  2. Comece pelas folhas (módulos utilitários com poucos imports) e vá avançando para dentro.
  3. Ligue o checkJs, ou adicione // @ts-check no topo de arquivos .js especí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.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR