ESLint Flat Configの深淵:型定義との「静かなる不整合」を封じ込めるアーキテクチャ設計
こんにちは。開発環境という「戦場」の最適化を専門とするアーキテクトです。
多くのエンジニアが、ESLintとPrettierを導入する際、単に「コードを綺麗にするもの」と捉えがちです。しかし、中規模以上のプロジェクトで本当に恐ろしいのは、「ESLintが解釈しているコードの姿」と「TypeScriptのコンパイラ(tsc)が見ているコードの姿」の間に生まれる微妙な乖離です。
特に、`@types/`のバージョンが微妙にズレたり、`tsconfig.json`の`paths`エイリアスがESLint側で正しく解決されていない時、開発者の脳内には「型エラーはないはずなのに、Lintで謎の警告が出る」というストレスが蓄積されます。
今日は、次世代のスタンダードである「Flat Config」を使い、この乖離を根絶する設計術を伝授します。これをマスターすれば、あなたのプロジェクトから「型定義由来の不可解なLint警告」は姿を消します。
—
1. なぜ「型定義の不整合」が起きるのか?
ESLintは、実は「TypeScriptそのもの」ではありません。TypeScriptのコードを「パース(解析)」して、AST(抽象構文木)というデータ構造に変換し、そこにルールを適用しているだけです。
もし、`tsconfig.json`で指定している型定義の参照範囲と、ESLintのプラグインが参照している型定義が異なれば、ESLintは「そのメソッドは存在しない」と判断したり、「any型が使われている」と誤検知します。これを防ぐには、「TypeScriptの解析エンジンをESLintの中に直接組み込む」という発想が必要です。
—
2. 実践:Flat Configによる「同期型」Lint設定
まずは、最新の`eslint.config.js`を用いた、堅牢なベースラインを構築しましょう。
必要なパッケージのインストール
単なるLintツールではなく、TypeScriptの型情報を直接参照するパーサーをインストールします。
ESLint本体と、TS解析のためのパーサー、プラグインを導入
npm install -D eslint @eslint/js typescript-eslint
`eslint.config.js` の設計図
この設定の肝は、`languageOptions`に`parserOptions`として`project: true`を渡すことです。これにより、ESLintはカレントディレクトリの`tsconfig.json`を自ら読み込み、コンパイラと同じ視界を確保します。
import js from “@eslint/js”;
import tseslint from “typescript-eslint”;
export default tseslint.config(
js.configs.recommended, // JSの基本ルール
…tseslint.configs.recommendedTypeChecked, // 型情報を利用した厳格なチェック
{
languageOptions: {
parserOptions: {
// プロジェクト内の tsconfig.json を読み込み、型情報を同期させる
project: true,
},
},
rules: {
// 現場で特に有効なルール:any型の乱用を物理的に防ぐ
“@typescript-eslint/no-explicit-any”: “error”,
},
}
);
—
3. 「型定義の不整合」を物理的に可視化する
開発現場で最も多いトラブルは、「`node_modules/@types`のバージョンが古く、最新のライブラリAPIに対応していない」ケースです。
これを解決するために、私たちは「TypeScriptの型チェックとLintをCIの同一フェーズで実行する」ことを推奨しています。
`package.json` に仕込むべきコマンド
{
“scripts”: {
// Lint実行前に型チェックを強制する(tsc –noEmit はJSを生成せずエラーのみを吐く)
“lint:strict”: “tsc –noEmit && eslint . –fix”
}
}
このコマンドを叩くことで、「型定義が壊れている環境ではLintすら通らない」という強力なガードレールが生まれます。もしESLintで警告が出るなら、それはコードの質の問題であり、環境構築の不備ではないと断言できる状態を作るのです。
—
4. 現場で震えるほど役立つ「黄金の運用ルール」
最後に、私が現場で必ず徹底させる「3つの鉄則」を共有します。
1. `tsconfig.json` をLintの真実とする: ESLint側に個別のパース設定を書かないでください。`project: true` を使い、常にコンパイラと同じ設定ファイルを見に行かせる。これが唯一の正解です。
2. `@types` は `devDependencies` に隔離する: ライブラリ本体のバージョンと型定義のバージョンは、`npm list` で定期的に確認し、乖離が生じた瞬間に依存関係をロックしてください。
3. Prettierとの共存は「ルール」で解決する: `eslint-config-prettier` を併用し、ESLintは「コードの論理(型安全性)」を、Prettierは「コードの見た目(インデント等)」を担当するという分業を徹底しましょう。
—
最後に:なぜこれが必要なのか?
あなたが今書いているその数行のコードは、将来的に何百人ものエンジニアが触れる資産になるかもしれません。そのとき、型定義の不整合という「目に見えないノイズ」が、バグの温床となります。
今回紹介した設定は、一見すると少し堅苦しいかもしれません。しかし、「環境がコードの正しさを保証してくれる」という感覚は、一度味わうと手放せなくなります。
開発効率を上げるというのは、楽をすることではありません。「本来悩む必要のないことで悩まないための仕組み」を、最初に作ることです。
さあ、あなたのプロジェクトの `eslint.config.js` を開き、このアーキテクチャを実装してみてください。あなたのコーディングライフが、よりクリアで、より自信に満ちたものになることを約束します。