🔌

ESLint コアルールの TypeScript 対応について

に公開

ESLint コアルールの TypeScript 対応について

ESLint v9.23.0 で ESLint のコアルールの TypeScript 対応が開始しました。

https://eslint.org/blog/2025/03/eslint-v9.23.0-released/

その後の ESLint のアップデートでもコアルールの TS 対応が進んでいます。ESLint コアの責務を増やすような機能追加は少し意外だと感じたので、その背景について調べてみました。

背景: 従来のコアルールの拡張方法の課題

ESLint のコアルールは JavaScript を想定して書かれたものであるが、TypeScript に対してもほぼ期待通り動作するルールが多い。TypeScript は JS のほぼ上位互換な言語であるため、TypeScript 用のパーサー (@typescript-eslint/parser) が吐き出す AST もほぼ JS の上位互換であり、パーサーさえ TS 用のものを使えば多くの ESLint コアルールを TS に対しても使うことができる。

しかし、一部のコアルールはそのままの挙動では TS では満足できないケースがあるため、@typescript-eslint プラグインでコアルールの拡張も行ってきた。プラグイン側で TS 特有の事情に合わせて挙動を修正したり、オプションを追加したりしている。しかし、その実装においては、コアルールを外から力技で拡張するような方式になっていた。

例えば no-unused-expressions は、TS 版の@typescript-eslint/no-unused-expressions では TS 特有の型キャスト構文 x as number; を考慮するように拡張されている。その実装を見ると、コアルールの挙動と内部実装を前提に拡張していることがわかる。

そんな中、ESLint v9.15.0 のリリースで問題が発生した。

ESLint コアルールの内部実装の変更により、@typescript-eslint プラグイン側で拡張していた部分が動かなくなった。

これに対して ESLint チームは、プラグイン開発者がコアルールの内部実装に依存することは推奨されないと正式に表明した。

以下の方針が決まり、ドキュメントにも反映された

  • コアルールは公開 API の一部ではない
  • ルールは ESLint 自体以外からロードすべきではない
  • ルールは予告なく変更または削除される可能性がある
  • プラグインがコアルールを拡張したい場合、ルールのファイルをプラグインのプロジェクトにコピーして独自に実装すること

対応: ESLint コアルールで TypeScript 対応することに

上記の方針は至極真っ当であるものの、プラグイン開発者のメンテナンス負担を増やす内容でもある。そこで @typescript-eslint プラグインのメンテナは、対策がないか議論を開始した。

議論の中で、ESLint としてはコアルールの拡張はさせないということが改めて確認されたが、一方でコアルールを TS にも対応する方針が示された。

ESLint コアルールのうち、構文レベルで TS も検証可能なものは ESLint コアルールで TS 対応する方針となった。一方で、TS の型情報を必要とするルールや TS 固有のコンテキストに関連するルールは、引き続き @typescript-eslint プラグインで対応していくことになっている。

また対応言語がわかるように、ルールのメタデータに meta.languagemeta.dialects を追加することも決まった。

例えば以下の no-empty-function の TS 対応を見ると、TS 用のオプションを @typescript-eslint プラグインから ESLint コアに移植しつつ、TS用のテストコードもガッツリ書いていることが分かる。

https://github.com/eslint/eslint/commit/dcd95aafa33a95c8102834af85129f6f398fe394

コアチームがそのような決定をした背景として、以下の discussion が参考になる。従来から、ここまで一般化した TypeScript での ESLint 利用が、プラグイン依存で標準ではできないということに対しては問題意識があったようだ。

今後も対応するルールを増やしていき、全て移行したところで @typescript-eslint プラグイン側の拡張ルールが非推奨になり、次期メジャーアップデートでの recommended の修正と非推奨ルールの削除で一連の取り組みが完了、という流れで進んでいくことが予想される。

感想

今回の ESLint のコアルールの TypeScript 対応は、単なる機能追加というよりも、プラグインエコシステムをどう設計するかという要素が大きいと言えるでしょう。昨今の TypeScript の流行も踏まえれば妥当な落とし所かもしれません。

ところでこの記事は、Cursor と VS Code (GitHub Copilot) の AI アシストを使って調査と執筆をしてみる練習として書いてみました。まだまだもどかしい動きが多いです。

Discussion