kb.erickguedes.com
TypeScript: Tipagem e Produtividade

tsconfig Profundo e Ferramentas

Aula 6 de 7

tsconfig.json — Modo Strict

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true,

    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitReturns": true,
    "exactOptionalPropertyTypes": true,
    "forceConsistentCasingInFileNames": true
  }
}

Explicação das Flags

FlagEfeito
noImplicitAnyErro se tipo não puder ser inferido
strictNullChecksnull/undefined não atribuíveis a outros tipos
strictFunctionTypesChecagem de variância em funções
strictBindCallApplyTipagem correta de bind/call/apply
strictPropertyInitializationPropriedades da classe devem ser inicializadas no construtor
noImplicitThisErro se this tiver tipo implícito any
noUnusedLocalsErro se variável local não for usada
exactOptionalPropertyTypesProps opcionais não aceitam undefined

lib, target, module

{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler"
  }
}
  • target: Versão JS de saída (ES5, ES2022, ESNext)
  • lib: Declarações de tipo disponíveis (DOM, ES2022, WebWorker)
  • module: Sistema de módulos (CommonJS, ESNext, NodeNext)
  • moduleResolution: Algoritmo de resolução (node, bundler, NodeNext)

paths e aliases

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}
// Em vez de
import { formatDate } from "../../../utils/date";

// Use
import { formatDate } from "@utils/date";

Project References

Projetos grandes podem ser divididos em subprojetos:

// tsconfig.json (raiz)
{
  "references": [
    { "path": "./packages/core" },
    { "path": "./packages/api" },
    { "path": "./packages/web" }
  ]
}
// packages/core/tsconfig.json
{
  "compilerOptions": {
    "composite": true,
    "outDir": "./dist",
    "rootDir": "./src"
  }
}
# Construir em modo incremental
tsc --build

# Limpar builds
tsc --build --clean

ESLint + typescript-eslint

npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
// eslint.config.js (Flat Config)
import tseslint from "@typescript-eslint/eslint-plugin";
import tsparser from "@typescript-eslint/parser";

export default [
  {
    files: ["src/**/*.ts"],
    languageOptions: {
      parser: tsparser,
      parserOptions: { project: "./tsconfig.json" },
    },
    plugins: { "@typescript-eslint": tseslint },
    rules: {
      "@typescript-eslint/no-explicit-any": "error",
      "@typescript-eslint/explicit-function-return-type": "warn",
      "@typescript-eslint/no-unused-vars": "error",
      "@typescript-eslint/strict-boolean-expressions": "error",
    },
  },
];

ts-node / tsx (Execução Direta)

# ts-node (tradicional)
npm install --save-dev ts-node
npx ts-node src/index.ts

# tsx (mais rápido, ESM nativo)
npm install --save-dev tsx
npx tsx src/index.ts
{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "start": "node dist/index.js",
    "build": "tsc",
    "typecheck": "tsc --noEmit"
  }
}

tsc CLI

# Compilar
tsc
tsc --project tsconfig.prod.json
tsc --noEmit                 # só verificar tipos
tsc --watch                  # modo observador

# Opções úteis
tsc --outDir dist
tsc --declaration            # gera .d.ts
tsc --declarationMap         # gera sourcemaps para .d.ts
tsc --sourceMap              # gera sourcemaps JS
tsc --listEmittedFiles       # lista arquivos gerados

Geração de Declaration Files (.d.ts)

{
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true,
    "emitDeclarationOnly": false,
    "outDir": "./dist"
  }
}

Para bibliotecas, gere .d.ts para que consumidores tenham tipos:

tsc                        # gera .js + .d.ts
tsc --emitDeclarationOnly  # só .d.ts (útil se outro bundler compila JS)

Lab: Configuração Profissional

{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "exactOptionalPropertyTypes": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}
# Verificação completa
npx tsc --noEmit
npx eslint src/
npx tsx src/index.ts

Configure tsconfig.json no início do projeto. Trocar strict depois exige corrigir centenas de erros. Invista tempo no setup uma vez.