Migrating to ESLint’s Flat Config: A Practical Guide
Learn how to replace .eslintrc with eslint.config.js, use JavaScript for conditional rules, and verify your flat config with eslint --print-config.
26 Mar 2026, 19:37 UTC

Problem: Scattered .eslintrc files make overrides painful
When a project grows, you often end up with multiple .eslintrc* files scattered across directories. Keeping track of which rule applies where becomes tedious, and sharing a common base configuration requires copying or complex extends chains.
Thesis: Flat config puts everything in JavaScript, giving you programmatic control
ESLint v8 introduced a flat config system where you export an array of plain JavaScript objects from eslint.config.js. Each object can target specific files, ignore patterns, language options, plugins, and rules. Because the config is just JavaScript, you can import shared configs, read environment variables, or generate parts of the configuration dynamically.
Understanding the flat config format
A flat config file exports an array. Each element in the array is a configuration object that is merged in order. The shape of an object mirrors the legacy .eslintrc keys: files, ignores, languageOptions, parserOptions, plugins, and rules. If you omit a key, ESLint uses its default.
Migrating an existing config
- Rename your existing
.eslintrc.js(or.eslintrc.json,.eslintrc.yml,.eslintrc) toeslint.config.js. - Wrap the exported object in an array:
module.exports = [ yourOldConfig ];. - If you used
extendsoroverrides, move those entries into the appropriate array elements (e.g., put overrides into separate objects with matchingfilespatterns).
Using JavaScript power: conditionals and shared configs
Because the config is JavaScript, you can do things that were awkward or impossible with the legacy format.
// eslint.config.js module.exports = [ { files: ['**/*.js'], languageOptions: { ecmaVersion: 2020, sourceType: 'module' }, rules: { semi: ['error', 'always'] } }, { files: ['**/*.ts'], languageOptions: { parser: '@typescript-eslint/parser' }, plugins: ['@typescript-eslint'], rules: { '@typescript-eslint/explicit-function-return-type': 'off' } } ];Trade‑offs and verification
- Requires ESLint v8 or newer; older versions will ignore
eslint.config.js. - Config errors are surfaced at runtime, making typos harder to spot. Use
eslint --print-config <file>to inspect the resolved configuration for a given file. - Some legacy plugins expect the old config shape; check for updated versions or wrap them with a compatibility layer if needed.
Practical check: after saving eslint.config.js, run npx eslint --print-config src/example.js and verify that the output contains a rules section with semi: [ 'error', 'always' ]. If you see the rule, the flat config is being applied.
Closing actions
- Upgrade ESLint:
npm i eslint@latest --save-dev - Add the flat config file as shown above.
- Run
npx eslint .to lint your project and confirm no new errors appear. - Whenever you edit the config, run
eslint --print-config <file>on a representative file to ensure the expected rules are active.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.