NeverThrowを触ろうと思ったらESLintのFlat Configを触っていた(中編)

の続き。Flat Configで eslint-plugin-neverthrow を使えるようにするぞー!

Flat Config?

そもそもFlat Configをよくわかっていない

ってところからスタート。へー。v9でFlat Configがデフォルトになっていて、v8は2024年10月からEOLなのか。

んで、次のv10で旧設定は使えなくなる。↓に「2024年末から2025年頭くらい」って書いてある。もうほんとにすぐだな。

僕は公式ドキュメントに最初からは入れないタイプ

なので、心のハードルを下げるために分かりやすそうな記事を読んでみる。↓安心のSajiさん@サイボウズフロントエンド。

記事を読みながら思ったんだけど、そもそもESLintの設定ファイルはこれまで雰囲気で触ってきてたので、旧の設定が新でどうなるかよりも新がどういうものなのか、という観点が僕には良さそう。この記事は新設定目線でまとめられているので、僕にとってちょうどいい。ありがたいー。

ざーっと読んで完全に理解した(= 雰囲気だけ理解した)

これまでは設定ファイルを独自で解決してたけど、JSの解決の仕組みを使うようにした。ってことかな。それは、分かりやすくていいな。

設定を配列で指定しておいて

  • その書き方や項目によっては全体に適用されるものがある
  • あとで書いたほうはそれまでの設定と合成されたりする

ってことみたいなので、その観点で公式ドキュメントをチェックすればよさそう。全部をチェックするのは大変だから、自分に関係しそうなところだけピックアップしてみるかな。

心のハードルが少し下がったところで

Flat Configの仕様を眺めてみる。

詳しくは↑を見てねってことで、ざっくり自分が見たことを書くと

複数の設定がどう重ね合わされるのかまだよくわかってないけど、下調べはこれくらいでいいかな。 eslint-plugin-neverthrow を使えるようにしていこー!

FlatCompatを使ってみる

eslint-plugin-neverthrow の旧設定をFlat Configで使うには、Sajiさんの記事でも紹介されているFlatCompatを使えばいいのかな?

やってみるかー!

❯ pnpm add -D @eslint/eslintrc

compat.config で囲んでみたらいいのかな

...

  ...compat.config({
    plugins: ['neverthrow'],
    rules: {
      'neverthrow/must-use-result': 'error',
    },
    parser: '@typescript-eslint/parser',
    parserOptions: {
      ecmaVersion: 2021,
      sourceType: 'module',
      project: ['./tsconfig.json'],
      tsconfigRootDir: __dirname,
    },
  })
];

これで設定は変換されているんだろうなと思う。

実行してみる→動かない!

❯ pnpm eslint src/hello-neverthrow.ts

Oops! Something went wrong! :(

ESLint: 9.15.0

Error: Error while loading rule 'neverthrow/must-use-result': types not available, maybe you need set the parser to @typescript-eslint/parser

むむー。「パーサーがちゃんと動いていないかも」って言われた。エラーメッセージを検索してみてもStack Overflowとかがヒットしなくて、よく見てみたらこのメッセージは eslint-plugin-neverthrow の↓の部分から出てるものだった。

そっか。だから調べても出てこないのか。eslint-plugin-neverthrow のGitHubリポジトリのIssueにOpenなものが一個あるくらい。メンテナンスは、んー、されてなさそう。

もうちょっと詳しく中を見てみよう

eslint-plugin-neverthrowmust-use-result ルールの create 関数の中でエラーになっていて↓この parserServices が取れてないっぽい。

    const parserServices = context.parserServices;
    const checker = parserServices?.program?.getTypeChecker();

ってことは、ESLintの設定が変わっただけじゃなくて、@typescript-eslint/parser の仕様も変わったってことなのかな?


追記ここから

後編を書いていて理解した。変わったのは @typescript-eslint/parser じゃなくてESLintのRules APIだった。

TypeError: context.getScope is not a function - ESLint - Pluggable JavaScript Linter

ESLint v9.0.0 introduces changes to the rules API that plugin rules use, which included moving some methods from the context object to the sourceCode object. If you’re seeing one of these errors, that means the plugin has not yet been updated to use the new rules API.

追記ここまで


@typescript-eslint にあるルールがどうやってるのかを見てみるか。

@typescript-eslint のルールを見てみる

例えば no-implied-eval

    const services = getParserServices(context);
    const checker = services.program.getTypeChecker();

こんな風に取得してる。eslint-plugin-neverthrow に手を入れて、これのマネをしてみるか。

つづく

えー。終わらなかった。つづく。

追記:つづき書いたー

bufferings.hatenablog.com