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.
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
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.