Pular para o conteúdo
TypeScript

Configurar ESLint com TypeScript: Guia

ESLint com TypeScript pega erros que o compilador deixa passar: variáveis não usadas, imports desnecessários, padrões inconsistentes. Configure o @typescript-eslint com flat config, regras recomendadas e Prettier sem

Por que isso é importante

Configurar ESLint com TypeScript: Guia. ESLint com TypeScript pega erros que o compilador deixa passar: variáveis não usadas, imports desnecessários, padrões inconsistentes. Configure o @typescript-eslint com flat config, regras recomendadas e Prettier sem

O Que Muda no ESLint com TypeScript

O ESLint padrão entende JavaScript. Pra ele entender TypeScript, precisa de duas coisas: um parser que leia a sintaxe TypeScript e um plugin com regras específicas pra tipos. O pacote typescript-eslint fornece os dois.

O parser (@typescript-eslint/parser) substitui o parser padrão do ESLint e entende interfaces, generics, type annotations e tudo mais que é exclusivo do TypeScript. Sem ele, o ESLint simplesmente não consegue ler seu código .ts.

O plugin (@typescript-eslint/eslint-plugin) traz regras que só fazem sentido com TypeScript. Por exemplo: proibir uso de any explícito, forçar tipo de retorno em funções, detectar Promises não tratadas. Essas regras vão além do que o compilador checa.

Com a versão 8 do ESLint, o flat config virou o padrão. Em vez de .eslintrc.json, você usa eslint.config.js (ou .mjs, .ts). A estrutura mudou, mas ficou mais simples e explícita. Vamos configurar usando o formato atual.

Passo a Passo: Setup Completo

Vamos instalar e configurar tudo do zero. Cada passo constrói em cima do anterior.

  1. Passo 1 - Instale as dependências: Rode npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin typescript. Se já tem TypeScript instalado, pode pular ele. O parser e o plugin precisam ser da mesma major version.
  2. Passo 2 - Crie o eslint.config.js: Na raiz do projeto, crie o arquivo de configuração flat. Importe o parser e o plugin, defina as regras e os arquivos que o ESLint deve analisar.
  3. Passo 3 - Configure o parser com o tsconfig: Aponte o parserOptions.project pro seu tsconfig.json. Isso habilita regras type-aware, que são as mais poderosas do typescript-eslint.
  4. Passo 4 - Ative as regras recomendadas: Use a configuração recommended do plugin como base. Ela já inclui as regras mais úteis. Depois customize conforme o projeto.
  5. Passo 5 - Configure os ignores: Ignore node_modules, dist, coverage e arquivos gerados. No flat config, ignores vão num objeto separado no array de configuração.
  6. Passo 6 - Adicione scripts no package.json: Crie um script lint (eslint src/) e um lint:fix (eslint src/ --fix). Rode no CI pra garantir que ninguém commita código com erro de lint.

Configuração Completa com Exemplos

Aqui vai a configuração passo a passo com código. Cada bloco é um estágio da configuração.

Instalação dos Pacotes

# Pacotes principais
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin

# Se quiser integrar com Prettier (recomendado)
npm install --save-dev prettier eslint-config-prettier

# Verificar versões compatíveis
npx eslint --version      # 9.x+
npx tsc --version          # 5.x+

Flat Config: eslint.config.js

// eslint.config.js
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";

export default tseslint.config(
  // Config base do ESLint
  eslint.configs.recommended,

  // Configs recomendadas do typescript-eslint
  ...tseslint.configs.recommended,

  // Configuração customizada
  {
    files: ["src/**/*.ts", "src/**/*.tsx"],
    languageOptions: {
      parser: tseslint.parser,
      parserOptions: {
        project: "./tsconfig.json",
      },
    },
    rules: {
      // Regras customizadas aqui
      "@typescript-eslint/no-unused-vars": ["error", {
        argsIgnorePattern: "^_",
        varsIgnorePattern: "^_",
      }],
      "@typescript-eslint/no-explicit-any": "warn",
      "@typescript-eslint/explicit-function-return-type": "off",
    },
  },

  // Ignores globais
  {
    ignores: [
      "node_modules/",
      "dist/",
      "build/",
      "coverage/",
      "*.config.js",
    ],
  },
);

Configuração com Prettier (sem conflitos)

// eslint.config.js com Prettier
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import prettier from "eslint-config-prettier";

export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.recommended,

  {
    files: ["src/**/*.ts", "src/**/*.tsx"],
    languageOptions: {
      parser: tseslint.parser,
      parserOptions: {
        project: "./tsconfig.json",
      },
    },
    rules: {
      "@typescript-eslint/no-unused-vars": ["error", {
        argsIgnorePattern: "^_",
      }],
      "@typescript-eslint/no-explicit-any": "error",
      "@typescript-eslint/no-floating-promises": "error",
      "@typescript-eslint/await-thenable": "error",
    },
  },

  // Prettier SEMPRE por último (desliga regras de formatação)
  prettier,

  { ignores: ["node_modules/", "dist/", "coverage/"] },
);

Regras Recomendadas pra TypeScript

// Regras que fazem diferença real no dia a dia
{
  rules: {
    // Proibir any explícito (força tipagem correta)
    "@typescript-eslint/no-explicit-any": "error",

    // Detectar Promises sem await ou .catch()
    "@typescript-eslint/no-floating-promises": "error",

    // Não usar await em valor que não é Promise
    "@typescript-eslint/await-thenable": "error",

    // Forçar retorno consistente em funções async
    "@typescript-eslint/require-await": "error",

    // Preferir nullish coalescing (??) ao invés de ||
    "@typescript-eslint/prefer-nullish-coalescing": "warn",

    // Preferir optional chaining (?.) ao invés de &&
    "@typescript-eslint/prefer-optional-chain": "warn",

    // Não usar type assertion desnecessário
    "@typescript-eslint/no-unnecessary-type-assertion": "error",

    // Variáveis não usadas (com exceção de _prefixadas)
    "@typescript-eslint/no-unused-vars": ["error", {
      argsIgnorePattern: "^_",
      varsIgnorePattern: "^_",
      destructuredArrayIgnorePattern: "^_",
    }],
  },
}

Scripts no package.json

{
  "scripts": {
    "lint": "eslint src/",
    "lint:fix": "eslint src/ --fix",
    "lint:strict": "eslint src/ --max-warnings 0",
    "format": "prettier --write src/",
    "check": "tsc --noEmit && eslint src/"
  }
}

// lint       - mostra erros sem corrigir
// lint:fix   - corrige automaticamente o que dá
// lint:strict - falha se tiver qualquer warning
// format     - formata com Prettier
// check      - checa tipos E lint de uma vez

Problemas Comuns na Configuração

Erros que travam o setup

Erro 'Parsing error: Cannot read file tsconfig.json': o parserOptions.project precisa apontar pro caminho correto do tsconfig. Se o eslint roda de uma pasta diferente, use caminho absoluto ou ajuste o tsconfigRootDir.

Conflito entre ESLint e Prettier: se os dois tentam formatar, dá guerra. Instale eslint-config-prettier e coloque SEMPRE como último item na config. Ele desliga as regras de formatação do ESLint e deixa o Prettier cuidar disso.

Regras type-aware muito lentas: regras como no-floating-promises precisam compilar o projeto inteiro pra funcionar. Em projetos grandes, isso deixa o lint lento. Use TIMING=1 eslint src/ pra encontrar quais regras são as mais pesadas.

Versões incompatíveis entre parser e plugin: o @typescript-eslint/parser e o @typescript-eslint/eslint-plugin precisam ter a mesma major version. Misturar v7 do parser com v6 do plugin causa erros misteriosos.

Usar .eslintrc quando o ESLint 9+ espera flat config: a partir do ESLint 9, flat config é o padrão. Se você ainda tem .eslintrc.json, migre pro eslint.config.js. O ESLint tem um migration assistant que ajuda.

Checklist de Setup do ESLint

  • Pacotes instalados: eslint, @typescript-eslint/parser, @typescript-eslint/eslint-plugin
  • eslint.config.js criado com flat config
  • Parser apontando pro tsconfig.json correto
  • Regras recomendadas ativadas como base
  • no-explicit-any configurado como error ou warn
  • no-floating-promises ativado pra código async
  • eslint-config-prettier adicionado por último (se usar Prettier)
  • Ignores configurados pra node_modules, dist e coverage
  • Scripts lint e lint:fix no package.json
  • Lint rodando no CI pipeline

Código Limpo com TypeScript e ESLint

ESLint com TypeScript é o combo que separa projetos profissionais de projetos amadores. No CrazyStack, todo o setup de lint vem configurado desde o primeiro commit: regras type-aware, Prettier integrado e CI que barra código fora do padrão. Você constrói um SaaS completo aprendendo as melhores práticas do mercado.

Se você quer um codebase que qualquer dev consegue manter sem dor de cabeça, comece pelo lint correto.