← Recipes

阅读中文版本

Migrate ESLint to Flat Config

Replace the eslintrc cascade with a flat eslint.config.js, compose typed rule sets explicitly, and keep overrides per file pattern.

~40 mineslinttoolingtypescript

Task

Adopt the ESLint flat config format with explicit composition instead of implicit cascading.

When to use this

The legacy eslintrc config inherits rules from many places implicitly, so it is unclear which rules apply and sorting out an override takes hours.

Prerequisites

  • ESLint v9 or v8 with flat config enabled
  • Plugin versions compatible with flat config

Steps

1. Create eslint.config.js exporting an array of config objects.

Expected output: Configuration is explicit and ordered.

2. Use the recommended configs from the plugins you trust.

Expected output: Baseline rules come from maintained presets.

3. Add file-scoped overrides with the files key.

Expected output: Overrides apply only where intended.

4. Add ignores at the top-level config instead of an ignore file.

npx eslint --print-config src/index.ts | head

Expected output: Ignoring is part of the same explicit config.

Troubleshooting

Problem

Plugin not compatible with flat config

Solution

Use a flat-config-aware version or the plugin compat helper; do not mix eslintrc plugins silently.

Problem

Rule unexpectedly not applied

Solution

Order matters in the array; later configs override earlier ones, so place overrides last.

Limitations

  • Flat config is still evolving, and some plugins lag behind it, which can force temporary workarounds.
  • Migration can surface previously masked rule violations that need triage.

Context

Adopt the ESLint flat config format with explicit composition instead of implicit cascading. The legacy eslintrc config inherits rules from many places implicitly, so it is unclear which rules apply and sorting out an override takes hours.

Steps

  1. Create eslint.config.js exporting an array of config objects. Expected: Configuration is explicit and ordered.
  2. Use the recommended configs from the plugins you trust. Expected: Baseline rules come from maintained presets.
  3. Add file-scoped overrides with the files key. Expected: Overrides apply only where intended.
  4. Add ignores at the top-level config instead of an ignore file. Expected: Ignoring is part of the same explicit config.
import js from '@eslint/js';
import tseslint from 'typescript-eslint';

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,
  { files: ['**/*.test.ts'], rules: { 'no-console': 'off' } },
  { ignores: ['dist/**'] },
];

Verify

  • Configuration is explicit and ordered.
  • Baseline rules come from maintained presets.
  • Overrides apply only where intended.
  • Ignoring is part of the same explicit config.

Limits

  • Flat config is still evolving, and some plugins lag behind it, which can force temporary workarounds.
  • Migration can surface previously masked rule violations that need triage.