ESLint Flat Config é o formato moderno de configuração do ESLint. Em vez de vários arquivos .eslintrc com herança implícita, o projeto usa um arquivo eslint.config.js, .mjs, .cjs ou, com configuração adicional, TypeScript. Esse arquivo exporta um array ordenado de objetos de configuração.
A principal mudança é tornar o comportamento explícito. Cada objeto pode definir arquivos, regras, plugins, parser, opções de linguagem e padrões ignorados. Quando mais de um objeto corresponde ao mesmo arquivo, as configurações são combinadas e os objetos posteriores podem sobrescrever os anteriores.
Instalação básica
npm install -D eslint @eslint/jsAdicione um script:
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix"
}
}Para um projeto ESM, crie eslint.config.js com:
import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
export default defineConfig([
{
files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
extends: [js.configs.recommended],
},
]);Em um projeto CommonJS, use eslint.config.cjs ou exporte com module.exports.
Como funciona o array de configuração
Cada item do array representa uma camada. Um objeto sem files se aplica aos arquivos reconhecidos por outras configurações e aos padrões padrão do ESLint. Para evitar ambiguidades em projetos mistos, prefira informar files explicitamente.
export default [
{
name: 'projeto/base',
files: ['src/**/*.js'],
rules: {
'no-unused-vars': 'error',
'prefer-const': 'error',
},
},
{
name: 'projeto/testes',
files: ['test/**/*.js'],
rules: {
'no-unused-expressions': 'off',
},
},
];O campo name não é obrigatório, mas melhora mensagens de erro e o inspetor de configuração.
files e glob patterns
O campo files usa padrões compatíveis com minimatch. Por padrão, ESLint reconhece .js, .mjs e .cjs. Para TypeScript, JSON, Markdown ou outras extensões, um plugin ou processador apropriado e padrões explícitos são necessários.
{
files: ['**/*.ts', '**/*.mts', '**/*.cts'],
}Os padrões são avaliados em relação à localização do arquivo de configuração, salvo quando uma configuração alternativa é fornecida pela opção --config.
Ignorando arquivos corretamente
Um objeto contendo apenas ignores funciona como ignore global:
import { defineConfig, globalIgnores } from 'eslint/config';
export default defineConfig([
globalIgnores([
'dist/',
'coverage/',
'.cache/',
'**/*.min.js',
]),
]);Também é possível usar um objeto simples:
{
ignores: ['dist/', 'coverage/'],
}Quando ignores aparece junto com rules ou outra chave, ele deixa de ser global e passa a limitar apenas aquele objeto. Essa diferença é uma das causas mais comuns de configurações inesperadas.
languageOptions
Opções antes espalhadas por parserOptions, env e globals ficam em languageOptions:
{
files: ['src/**/*.js'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
process: 'readonly',
Buffer: 'readonly',
},
},
}Para evitar manter globals manualmente, instale o pacote globals:
npm install -D globalsimport globals from 'globals';
{
languageOptions: {
globals: globals.node,
},
}ESM e CommonJS no mesmo projeto
Flat Config facilita aplicar opções diferentes:
export default [
{
files: ['**/*.js', '**/*.mjs'],
languageOptions: {
sourceType: 'module',
},
},
{
files: ['**/*.cjs'],
languageOptions: {
sourceType: 'commonjs',
},
},
];Isso combina bem com pacotes que usam type: module, mas ainda mantêm scripts legados em CommonJS.
Configurando plugins
No formato flat, plugins são importados como objetos:
import importPlugin from 'eslint-plugin-import';
export default [
{
files: ['**/*.js'],
plugins: {
import: importPlugin,
},
rules: {
'import/no-unresolved': 'error',
'import/no-duplicates': 'error',
},
},
];O nome usado na chave plugins define o prefixo das regras. Não precisa ser idêntico ao nome do pacote, mas manter o nome convencional reduz confusão.
Usando configurações recomendadas
O pacote @eslint/js fornece recommended. Plugins também podem publicar configs prontas. Dependendo do formato exportado pelo plugin, a configuração pode ser inserida diretamente no array ou em extends.
import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
export default defineConfig([
{
files: ['**/*.js'],
extends: [js.configs.recommended],
rules: {
'no-console': 'warn',
},
},
]);Sempre limite configurações compartilhadas com files quando possível. Sem isso, regras de JavaScript podem atingir arquivos processados por outros plugins.
Flat Config com TypeScript
Uma configuração comum usa typescript-eslint:
npm install -D typescript typescript-eslintimport eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import { defineConfig } from 'eslint/config';
export default defineConfig([
eslint.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.ts'],
rules: {
'@typescript-eslint/no-explicit-any': 'warn',
},
},
]);Para regras que dependem de tipos, configure o projeto TypeScript conforme a documentação do plugin. Essas regras aumentam o tempo de lint, então separe tarefas rápidas das verificações completas quando o repositório for grande.
Arquivo de configuração em TypeScript
ESLint aceita eslint.config.ts, mas em Node.js pode exigir jiti ou flags experimentais de remoção de tipos, dependendo da versão. O formato JavaScript costuma ser a opção mais simples e portátil.
Se escolher TypeScript:
npm install -D jitiO ESLint não faz type checking da configuração e não aplica automaticamente opções do tsconfig.json.
linterOptions
Use linterOptions para controlar comentários de configuração:
{
linterOptions: {
noInlineConfig: false,
reportUnusedDisableDirectives: 'error',
reportUnusedInlineConfigs: 'warn',
},
}Relatar eslint-disable não utilizados evita exceções permanentes depois que o código é corrigido.
Configuração para testes
Arquivos de teste costumam precisar de globals e regras diferentes:
import globals from 'globals';
{
name: 'projeto/testes',
files: ['test/**/*.js', '**/*.test.js'],
languageOptions: {
globals: {
...globals.node,
...globals.mocha,
},
},
rules: {
'no-unused-expressions': 'off',
},
}Aplicar exceções apenas aos testes é melhor que desativar regras em todo o projeto.
Monorepos
Em workspaces, uma configuração raiz pode atender todos os pacotes. Use basePath ou padrões:
{
name: 'monorepo/api',
basePath: 'apps/api',
files: ['**/*.js'],
rules: {
'no-console': 'error',
},
}Também é possível colocar um eslint.config.js em um subdiretório. ESLint pesquisa a partir do arquivo analisado e sobe pelos diretórios até encontrar uma configuração.
Depurando a configuração
Use o inspetor:
npx eslint --inspect-config src/server.jsOu imprima a configuração final:
npx eslint --print-config src/server.jsEsses comandos mostram quais objetos correspondem ao arquivo, quais regras prevalecem e por que um arquivo foi ignorado.
Migração de eslintrc
Durante a migração, liste:
- extends e presets usados;
- plugins e parsers;
- overrides por extensão;
- ambientes e globals;
- ignore patterns;
- regras locais.
Converta cada override em um objeto com files. Substitua env por globals e opções de linguagem. Não mantenha os dois formatos ativos sem entender qual versão do ESLint está lendo cada arquivo.
Integração com CI
- run: npm ci
- run: npm run lint
Use uma versão fixa de ESLint no lockfile. Para impedir que avisos se acumulem:
eslint . --max-warnings=0Boas práticas
Nomeie objetos, mantenha regras agrupadas por finalidade, limite com files, use ignores globais explícitos e valide a configuração em arquivos reais. Evite ativar js/all em produção, pois o conjunto muda entre versões.
Flat Config funciona bem ao lado de npm Workspaces no Node.js, versões determinísticas com Corepack no Node.js, testes com Node Test Runner e automação com GitHub Actions no Node.js.
Consulte a documentação oficial de arquivos de configuração do ESLint e o guia oficial de migração para Flat Config.




