Flat Config とは?

Flat ConfigはESLint v9で正式採用された新しい設定形式です。従来の .eslintrc.*(JSON/YAML/JS)に代わり、eslint.config.js(または .mjs/.ts)を使います。

なぜ Flat Config に変わったのか?

従来の課題Flat Config の解決策
設定の優先順位が複雑配列で上から順に適用、シンプル
extends/overrides のネストが深いフラットな配列構造
プラグインの解決が暗黙的明示的にimportして渡す
.eslintrc を探すディレクトリ探索1ファイルで完結

バージョン対応状況

ESLintバージョンFlat Config.eslintrc
v8.x実験的サポートデフォルト
v9.xデフォルト非推奨
v10.x(予定)デフォルト削除

基本構造

最小構成

// eslint.config.js
export default [
  {
    rules: {
      "no-unused-vars": "warn",
      "no-console": "warn",
    },
  },
];

構造の説明

Flat Config は設定オブジェクトの配列です。配列の各要素が順番に適用されます。

export default [
  // 1. 全ファイルに適用される基本ルール
  {
    rules: {
      "no-unused-vars": "warn",
    },
  },

  // 2. TypeScriptファイルにだけ適用
  {
    files: ["**/*.ts", "**/*.tsx"],
    rules: {
      // TypeScript固有のルール
    },
  },

  // 3. テストファイルにだけ適用
  {
    files: ["**/*.test.ts", "**/*.spec.ts"],
    rules: {
      "no-console": "off",
    },
  },
];

ファイル指定とグローバル無視

files と ignores

export default [
  // 特定のファイルだけに適用
  {
    files: ["src/**/*.js", "src/**/*.ts"],
    rules: {
      "no-console": "warn",
    },
  },

  // グローバル無視(files なしで ignores だけ)
  {
    ignores: [
      "dist/",
      "node_modules/",
      "*.config.js",
      "**/*.min.js",
    ],
  },
];

注意: ignores だけの設定オブジェクトはグローバル無視になります。files と一緒に書くと、そのオブジェクト内でのみ有効です。

プラグインの設定

従来との違い

// 旧: .eslintrc.json(文字列で指定、暗黙的に解決)
{
  "plugins": ["@typescript-eslint"],
  "extends": ["plugin:@typescript-eslint/recommended"]
}

// 新: eslint.config.js(明示的にimport)
import tseslint from "typescript-eslint";

export default [
  ...tseslint.configs.recommended,
];

TypeScript + React の設定例

// eslint.config.js
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import react from "eslint-plugin-react";
import reactHooks from "eslint-plugin-react-hooks";

export default [
  // 基本ルール
  js.configs.recommended,

  // TypeScript
  ...tseslint.configs.recommended,

  // React
  {
    files: ["**/*.{jsx,tsx}"],
    plugins: {
      react,
      "react-hooks": reactHooks,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      "react/react-in-jsx-scope": "off",
      "react/prop-types": "off",
    },
    settings: {
      react: {
        version: "detect",
      },
    },
  },

  // テストファイル
  {
    files: ["**/*.test.{ts,tsx}", "**/*.spec.{ts,tsx}"],
    rules: {
      "@typescript-eslint/no-explicit-any": "off",
    },
  },

  // 無視
  {
    ignores: ["dist/", "node_modules/", ".next/"],
  },
];

Prettier との併用

import js from "@eslint/js";
import prettier from "eslint-config-prettier";

export default [
  js.configs.recommended,

  // Prettier と競合するルールを無効化(必ず最後に置く)
  prettier,
];

languageOptions

従来の envparserparserOptionslanguageOptions にまとめられました。

export default [
  {
    languageOptions: {
      // ECMAScript バージョン
      ecmaVersion: 2025,

      // モジュールタイプ
      sourceType: "module",

      // グローバル変数
      globals: {
        console: "readonly",
        process: "readonly",
        Buffer: "readonly",
        __dirname: "readonly",
      },

      // パーサーオプション
      parserOptions: {
        ecmaFeatures: {
          jsx: true,
        },
      },
    },
  },
];

globals パッケージの活用

import globals from "globals";

export default [
  {
    languageOptions: {
      globals: {
        ...globals.browser,    // window, document, etc.
        ...globals.node,       // process, __dirname, etc.
        ...globals.es2025,     // Promise, Map, Set, etc.
      },
    },
  },
];

.eslintrc からの移行手順

1. パッケージをアップデート

npm install eslint@latest --save-dev

2. 自動移行ツールを使う

npx @eslint/migrate-config .eslintrc.json

これで eslint.config.mjs が生成されます。

3. 手動調整のポイント

extends → スプレッド構文

// 旧
{ "extends": ["eslint:recommended"] }

// 新
import js from "@eslint/js";
export default [js.configs.recommended];

env → globals

// 旧
{ "env": { "browser": true, "node": true } }

// 新
import globals from "globals";
export default [{
  languageOptions: {
    globals: { ...globals.browser, ...globals.node }
  }
}];

overrides → 別の設定オブジェクト

// 旧
{
  "overrides": [{
    "files": ["*.test.js"],
    "rules": { "no-console": "off" }
  }]
}

// 新
export default [
  { files: ["**/*.test.js"], rules: { "no-console": "off" } }
];

4. 旧ファイルを削除

rm .eslintrc.json .eslintrc.js .eslintrc.yml .eslintignore

.eslintignoreignores に統合されるため不要です。

実践的な設定テンプレート

Node.js + TypeScript プロジェクト

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

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

  {
    languageOptions: {
      globals: {
        ...globals.node,
      },
    },
    rules: {
      "@typescript-eslint/no-unused-vars": ["warn", {
        argsIgnorePattern: "^_",
        varsIgnorePattern: "^_",
      }],
      "@typescript-eslint/explicit-function-return-type": "off",
      "@typescript-eslint/no-explicit-any": "warn",
    },
  },

  {
    files: ["**/*.test.ts"],
    rules: {
      "@typescript-eslint/no-explicit-any": "off",
    },
  },

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

  prettier,
);

トラブルシューティング

よくあるエラー

「Key “plugins”: Key “xxx”: Expected an object」

プラグインのimport方法が間違っています。default exportを確認してください。

// NG
import xxx from "eslint-plugin-xxx";
plugins: { xxx: xxx }

// OK(プラグインの export を確認)
import xxx from "eslint-plugin-xxx";
plugins: { xxx }

「Unexpected key “env” found」

Flat Config では env は使えません。languageOptions.globals に変更してください。

「.eslintrc と eslint.config.js が両方ある」

ESLint v9 は eslint.config.js を優先します。旧ファイルは削除してください。

まとめ

項目旧(.eslintrc)新(Flat Config)
ファイル形式JSON/YAML/JSJS/MJS/TS
設定構造ネスト(extends/overrides)フラット配列
プラグイン文字列で指定importして渡す
環境設定envglobals パッケージ
無視設定.eslintignoreignores

Flat Config はシンプルで予測しやすい設定形式です。新規プロジェクトではFlat Configを採用し、既存プロジェクトも段階的に移行していきましょう。


ESLintの設定ファイル(JSON形式)を整形するには、AssistyのJSONフォーマッターが便利です。