tsconfig.json: as opções que realmente importam

1. Introdução ao tsconfig.json

O arquivo tsconfig.json é o coração da configuração do TypeScript. Ele informa ao compilador tsc como processar seu código, quais arquivos incluir, para qual versão do JavaScript compilar e quais regras de tipo aplicar. Quando você executa tsc sem argumentos, o compilador procura automaticamente por um tsconfig.json no diretório raiz do projeto.

A estrutura básica do arquivo contém três seções principais:

{
  "compilerOptions": {
    // Opções do compilador
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}
  • compilerOptions: Define como o TypeScript compila o código
  • include: Padrões de arquivos a serem incluídos
  • exclude: Padrões de arquivos a serem ignorados
  • files: Lista explícita de arquivos (alternativa ao include)

2. Controle de Saída e Compatibilidade

As opções de saída determinam como seu código TypeScript será transformado em JavaScript executável.

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "outDir": "./dist",
    "rootDir": "./src"
  }
}
  • target: Define a versão ECMAScript de saída. ES5 para máxima compatibilidade, ES2020 para projetos modernos, ESNext para usar os recursos mais recentes
  • module: Sistema de módulos. CommonJS para Node.js, ESNext para bundlers modernos, UMD para bibliotecas universais
  • outDir: Diretório onde os arquivos compilados serão salvos
  • rootDir: Diretório raiz do código fonte, usado para preservar a estrutura de diretórios na saída

3. Rigidez e Segurança de Tipos

O modo estrito é essencial para aproveitar todo o potencial do TypeScript.

{
  "compilerOptions": {
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true
  }
}
  • strict: Ativa todas as verificações de tipo rigorosas, incluindo strictNullChecks e noImplicitAny
  • noUnusedLocals: Gera erro para variáveis locais não utilizadas
  • noUnusedParameters: Gera erro para parâmetros de função não utilizados
  • strictFunctionTypes: Garante segurança em tipos de funções, especialmente em callbacks
  • strictBindCallApply: Verifica tipos corretamente em bind, call e apply

4. Resolução de Módulos e Paths

Uma configuração adequada de resolução de módulos evita imports confusos e facilita a manutenção.

{
  "compilerOptions": {
    "moduleResolution": "bundler",
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"]
    },
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
  }
}
  • moduleResolution: node para projetos Node.js tradicionais, bundler para projetos com Vite/Webpack
  • baseUrl: Diretório base para resolução de módulos não relativos
  • paths: Cria aliases para imports limpos, como import { Button } from '@components/Button'
  • esModuleInterop: Permite importar módulos CommonJS como módulos ES
  • allowSyntheticDefaultImports: Permite imports padrão de módulos sem export default

5. Suporte a JavaScript e Declarações

Essas opções são cruciais para migração gradual e criação de bibliotecas.

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  }
}
  • allowJs: Permite compilar arquivos JavaScript junto com TypeScript
  • checkJs: Realiza verificação de tipo em arquivos JavaScript
  • declaration: Gera arquivos .d.ts com as declarações de tipo
  • declarationMap: Cria mapas de origem para os arquivos .d.ts
  • sourceMap: Gera arquivos .map para depuração no navegador

6. Otimizações e Performance

Em projetos grandes, essas opções podem reduzir drasticamente o tempo de compilação.

{
  "compilerOptions": {
    "skipLibCheck": true,
    "incremental": true,
    "tsBuildInfoFile": "./.tsbuildinfo",
    "removeComments": true,
    "noEmitOnError": true
  }
}
  • skipLibCheck: Ignora checagem de tipos em arquivos de declaração (node_modules), acelerando a compilação
  • incremental: Habilita compilação incremental, reutilizando informações de compilações anteriores
  • tsBuildInfoFile: Define onde salvar o arquivo de informações de build incremental
  • removeComments: Remove comentários do código compilado
  • noEmitOnError: Não gera arquivos de saída se houver erros de compilação

7. Configurações Avançadas e Projetos Monorepo

Para projetos complexos e monorepos, estas opções são indispensáveis.

{
  "compilerOptions": {
    "composite": true,
    "forceConsistentCasingInFileNames": true,
    "isolatedModules": true,
    "resolveJsonModule": true,
    "downlevelIteration": true
  },
  "references": [
    { "path": "./packages/core" },
    { "path": "./packages/utils" }
  ]
}
  • references: Permite dividir o projeto em sub-projetos com composite: true
  • forceConsistentCasingInFileNames: Garante que nomes de arquivos usem caixa consistente
  • isolatedModules: Garante que cada arquivo pode ser compilado isoladamente
  • resolveJsonModule: Permite importar arquivos JSON como módulos
  • downlevelIteration: Fornece suporte a iteradores em versões mais antigas do JavaScript

8. Boas Práticas e Exemplos Práticos

Checklist para novo projeto TypeScript:

  • [ ] strict: true — Sempre ative o modo estrito
  • [ ] target: "ES2020" ou superior — Use versões modernas
  • [ ] module: "ESNext" — Para projetos com bundler
  • [ ] skipLibCheck: true — Acelera a compilação
  • [ ] esModuleInterop: true — Evita problemas com imports
  • [ ] forceConsistentCasingInFileNames: true — Consistência entre sistemas

Exemplo para aplicação web (React/Vite):

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "jsx": "react-jsx",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

Exemplo para biblioteca Node.js:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "moduleResolution": "node",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

Dominar o tsconfig.json é essencial para extrair o máximo de produtividade e segurança do TypeScript. Cada opção tem seu propósito, e entender quando e por que usá-las transforma seu fluxo de desenvolvimento.

Referências