🧊

oxlintに`--type-aware`オプションがきた

Oxlint Type-Aware Preview | The JavaScript Oxidation Compiler https://oxc.rs/blog/2025-08-17-oxlint-type-aware.html

まだプレビューではあるけど、こいつ動くぞ!って感じ。

TL;DR

  • oxlintでも、typescript/no-floating-promisesみたいな、TSの型情報を使ったルールが動くようになった
  • Biomeみたく、RustでTSの型チェッカーを簡易実装したわけではない
  • 内部的には、TSのGoリライトであるtypescript-goを使ったtypescript-eslint/tsgolintを使ってる
    • さらに厳密には、そのforkであるoxc-project/tsgolint
  • oxlintが子プロセスでtsgolintを立てて指示を出すイメージ

まあ大事なことはだいたい告知ブログに書いてある。

現状で利用可能なルール

  • typescript/await-thenable
  • typescript/no-array-delete
  • typescript/no-base-to-string
  • typescript/no-confusing-void-expression
  • typescript/no-duplicate-type-constituents
  • typescript/no-floating-promises
  • typescript/no-for-in-array
  • typescript/no-implied-eval
  • typescript/no-meaningless-void-operator
  • typescript/no-misused-promises
  • typescript/no-misused-spread
  • typescript/no-mixed-enums
  • typescript/no-redundant-type-constituents
  • typescript/no-unnecessary-boolean-literal-compare
  • typescript/no-unnecessary-template-expression
  • typescript/no-unnecessary-type-arguments
  • typescript/no-unnecessary-type-assertion
  • typescript/no-unsafe-argument
  • typescript/no-unsafe-assignment
  • typescript/no-unsafe-call
  • typescript/no-unsafe-enum-comparison
  • typescript/no-unsafe-member-access
  • typescript/no-unsafe-return
  • typescript/no-unsafe-type-assertion
  • typescript/no-unsafe-unary-minus
  • typescript/non-nullable-type-assertion-style
  • typescript/only-throw-error
  • typescript/prefer-promise-reject-errors
  • typescript/prefer-reduce-type-parameter
  • typescript/prefer-return-this-type
  • typescript/promise-function-async
  • typescript/related-getter-setter-pairs
  • typescript/require-array-sort-compare
  • typescript/require-await
  • typescript/restrict-plus-operands
  • typescript/restrict-template-expressions
  • typescript/return-await
  • typescript/switch-exhaustiveness-check
  • typescript/unbound-method
  • typescript/use-unknown-in-catch-callback-variable

これら40のルールがoxlint-tsgolintで実装されてて、そのすべてがoxlint側でも利用可能になってる。

https://github.com/oxc-project/tsgolint/tree/5ff6f7a748c9f98a97aa72ff767e0df27cfe3a19/internal/rules https://github.com/oxc-project/oxc/tree/0ff92745ead06ac02ac865f17f9b0df8c318e307/crates/oxc_linter/src/rules/typescript

typescript-eslintには、全部で60くらいtype-checkedなルールがあったはず。

https://typescript-eslint.io/rules/?=typeInformation

コードを読む

個人的な本題。

npmから落とせるoxlintバイナリのエンドポイントは、OXCのリポジトリのapps/oxlintにある。 そしてまずここで、--type-awareオプションを見てる。

https://github.com/oxc-project/oxc/blob/87dec8284e76887c066e5f392e55c1219e082a76/apps/oxlint/src/command/lint.rs#L49-L51

そして、オプションがあったらtsgolintのプロセスを実行する。

https://github.com/oxc-project/oxc/blob/87dec8284e76887c066e5f392e55c1219e082a76/apps/oxlint/src/lint.rs#L299-L308

パスが解決できないとか、なんかpanicしたとか、そういう場合にはここでエラーを表示して終わり。

TsGoLintState::new().lint()

https://github.com/oxc-project/oxc/blob/87dec8284e76887c066e5f392e55c1219e082a76/crates/oxc_linter/src/tsgolint.rs

現状はこのファイルに全てが詰まってるので追いやすい。

  • new(cwd, config_store)
  • lint(paths, error_sender)
    • pathsに対して、config_storeで指定されたルールを実行していく
    • tsgolintheadlessモードで子プロセスとしておき、stdin/stdoutでJSONをやり取り
    • 問題が見つかったらerror_senderDiagnosticsを報告

以上、ってくらいに構造はシンプル。

tsgolintプロセスとやり取りするJSONのデータ変換と、見つかったDiagnosticをリアルタイムにバッファする処理が行数のほとんど。

oxlint側のルール実装も、それがtsgolintに投げるやつですっていうマーカーがあるだけ。

https://github.com/oxc-project/oxc/blob/87dec8284e76887c066e5f392e55c1219e082a76/crates/oxc_linter/src/rules/typescript/no_floating_promises.rs#L73

tsgolint

Goはよくわからんけどざっと見ておく。

TSのAPIは、typescript-goの公開されてるAPIを使っているわけではなく、独自にコンパイルして、必要なAPIをshimしてるとのこと。

https://github.com/oxc-project/tsgolint/blob/5ff6f7a748c9f98a97aa72ff767e0df27cfe3a19/tools/gen_shims/README.md

そのほかにも、typescript-goに対するパッチとかもあった。

https://github.com/oxc-project/tsgolint/blob/5ff6f7a748c9f98a97aa72ff767e0df27cfe3a19/patches/README.md

メンテナンスしていくのはそこそこ大変そうに見えるな。

今後は

これも告知ブログに書いてあるけど、巨大モノレポでのパフォーマンス改善とか、IDEサポートとか、ルール追加とか、今後に乞うご期待。

oxlintはカスタムルールをJSで書けるようになる予定があるけど、このTSの型情報も使えるように・・・ならんか流石に。

はよAIが賢くなって、TSCをRustでリライトしてくれますように。