ESLint の設定をエディタ補完や型検査つきで書く

ESLint の設定に関する TypeScript の型情報を提供してくれる eslint-define-config (ESLint 非公式プロジェクト) のご紹介.

github.com

使い方

eslintrc の場合は defineConfig, Flat Config の場合は defineFlatConfig で設定を囲むだけで VSCode などエディタ上で補完が効くようになります. これらの関数の実体はただの恒等関数なので, 型情報を提供する以上のことは何もしません (つまり何も気にせず追加できます).

import { defineFlatConfig } from "eslint-define-config";

export default defineFlatConfig([
  // ...
  {
    rules: {
      "no-console": "error",
    },
  },
  // ...
]);

型検査も有効にするのであれば // @ts-check をファイル先頭に書くなどしておきましょう. (どのみち設定が間違っていれば ESLint の実行時にエラーになってくれたりするので, そこまではしなくても良いとも思っています.)

ESLint プラグインを使う

プラグインが提供するルールの型情報はデフォルトでは提供されていません (v2.0.0 以降). ただし拡張の仕組みが用意されているので, プラグインなどから追加の型情報を提供できるようになっています.

型情報を提供するには, 以下のような形で eslint-define-config モジュールを拡張します. プラグインの作者はプラグイン側からなんらか提供するようにしておくとユーザーが喜ぶかもしれません.

declare module "eslint-define-config" {
  interface CustomRuleOptions {
    "my-plugin/my-rule": [{ myOption?: boolean }];
  }
}

とはいえ 2024-02 時点ではプラグインがこのような型情報を提供していることはおそらくほぼ無く, 一般的ないくつかのプラグインについては @eslint-types/* から型情報が提供されていたりします.

型情報がなくても補完や型検査がされないだけで, プラグインが使えないということにはなりませんので, あったら便利に使うくらいの気持ちでいるのが良いと思います. (実際のところ ESLint の設定はそんなに頻繁に書き換えるものではないので, 型情報があることによる利益はどうせ限定的.)

ところで

Flat Config ではユーザーが自由にプラグインの名前 (ルール名の prefix) を決めることができます.

export default defineFlatConfig([
  // ...
  {
    plugins: {
      "whatever": myPlugin,
    },
    rules: {
      "whatever/my-rule": "error",
    },
  },
  // ...
]);

上で紹介したようなルールの型情報は基本的には固定の prefix 込みで提供することになるので, 自由に名前をつけられてしまうと困りますね (解決策なし).

余談

ライブラリでもバンドラを使うと便利, tree-shaking もされるし, などと言っていたところ, せっかく書いたモジュール拡張が tree-shaking によって捨てられてしまいました. ままなりません.

susisu.hatenablog.com

Pull Request を作るのに一時間以上かかったら捨ててる

一時間は大体の目安でちゃんと測ってない.

  • PR の作成に時間がかかるときは, 何らか良くないことが起きている可能性が高い
    • 試行錯誤を繰り返している
    • 変更の規模が過大になっている
  • 良くないことが起きているなら, そのまま続けて余計なコストをかけるよりも捨てた方が良い
    • 試行錯誤を繰り返していたなら, そこまでは勉強か練習だと思って捨てる
    • 変更の規模が過大になっていたなら, 分割して作り直すために捨てる
  • 捨てることを躊躇わない
    • 時間をかけるほど引き返しづらくなるので, 一時間くらいで打ち切る
    • 一時間の手戻りなら一時間で取り返せる. なんなら知識が増えている分もっと短くて済む
    • 思ったより進んでいなくても, そのまま思っていたところまで進めようとはせずに諦めて捨てる. とにかく良くないことが起きている可能性が高いので立ち止まるべきで, 思ったところまで進められる (良くない状態に陥らなくなる) 状態は立ち止まって反省した先にある
    • いいから捨てろ. 大抵はコードそのものよりもコードを書くことで得た知識の方が圧倒的に価値があるので, コードを捨てるのは大したことじゃない
  • 全ての作業を一時間で終わらせるという話ではない
    • N 時間を一回でやっているところを一時間を一回にするのではなく, 一時間を N 回やるという話
  • 品質で手を抜くという話でもない
    • 一時間で品質が低い状態までしか辿り着けなかったとしたら, そこで完成とするのではなく, 一旦捨てて品質が高い状態に辿り着けるような進め方を考えるという話
    • 低品質で作る → 高品質化する のように作業を分けるのも, 結局後者が実行されないことがあるので理想的ではない. 高品質で作る → 高品質で作る と作業を分けられた方が良くて, そうできるようになるためには実際にこのように分けようとしてみるしかない