Slide 1

Slide 1 text

Oxlintはいかにして tsgolintのlint ruleを呼び出しているのか 2026-5-22 TSKaigi 2026 @syumai

Slide 2

Slide 2 text

syumai X: @__syumai Website: https://syum.ai © LayerX Inc. whoami LayerX ソフトウェアエンジニア バクラクヘルプデスク エージェントを開発中 主にTypeScriptを書いてます ECMAScript 仕様輪読会 / Asakusa.go 主催

Slide 3

Slide 3 text

今日話すこと © LayerX Inc. Oxlintとは tsgolintとは tsgolintのlintルールの書き方 Oxlintによるtsgolintの呼び出し方法 3

Slide 4

Slide 4 text

Oxlintとは © LayerX Inc. Oxcプロジェクトのlinter https://oxc.rs/ Rust製の高速なJavaScript向けTool chain Oxcはlinter, formatter, parser, transformerなどを含む ESLint互換が特徴 設定はESLint v8の形式 (Flat configは非対応、migration toolあり) ESLintのJS pluginも動作する (v9以降のAPIをサポート) 開発元はViteを開発するVoidZero (https://voidzero.dev/) OxlintはVite+の vp check サブコマンドとして取り込まれている 4

Slide 5

Slide 5 text

https://oxc.rs/#feature-linter © LayerX Inc. 5

Slide 6

Slide 6 text

https://viteplus.dev/#feature-check © LayerX Inc. 6

Slide 7

Slide 7 text

Oxlintとは © LayerX Inc. Oxlint単体では、TypeScriptの型情報を使ったlintができない 構文解析のみで対応できるものはサポートしている no-explicit-any など 型情報がないと対応できないlintルールもある no-floating-promises , no-for-in-array など 7

Slide 8

Slide 8 text

https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-explicit-any © LayerX Inc. 8

Slide 9

Slide 9 text

https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-explicit-any © LayerX Inc. 9

Slide 10

Slide 10 text

https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-explicit-any © LayerX Inc. 10

Slide 11

Slide 11 text

https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-for-in-array © LayerX Inc. 11

Slide 12

Slide 12 text

https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-for-in-array © LayerX Inc. 12

Slide 13

Slide 13 text

https://oxc.rs/docs/guide/usage/linter/rules/typescript/no-for-in-array © LayerX Inc. 13

Slide 14

Slide 14 text

tsgolintとは © LayerX Inc. 元は、2025年7月にtypescript-eslintのチームがリリースしたtsgoベースのLinter https://github.com/typescript-eslint/tsgolint これを、Oxcプロジェクトとしてforkし、Oxlintと連携できるようにしたもの https://github.com/oxc-project/tsgolint 実装は全部Go tsgoのinternal packageの中身を無理矢理公開して使用 Oxlint + tsgolintはESLint + typescript-eslintより10倍程度速いらしい https://oxc.rs/blog/2025-12-08-type-aware-alpha.html#performance 14

Slide 15

Slide 15 text

https://speakerdeck.com/syumai/how-tsgolint-exposes-typescript-gos-private-apis (アーカイブあり) © LayerX Inc. 15

Slide 16

Slide 16 text

Oxlint + tsgolintの使い方 © LayerX Inc. 16

Slide 17

Slide 17 text

tsgolintによるlint ruleの書き方 © LayerX Inc. tsgolintが内部で利用可能な形で公開したtsgoのast / checker packageを使って解析 ast packageで、欲しいNodeを探す checker packageで、欲しい型情報とのマッチを確認 17

Slide 18

Slide 18 text

no-for-in-arrayの例 https://github.com/oxc-project/tsgolint/blob/v0.23.0/internal/rules/no_for_in_array/no_for_in_array.go © LayerX Inc. 18

Slide 19

Slide 19 text

no-for-in-arrayの例 https://github.com/oxc-project/tsgolint/blob/v0.23.0/internal/rules/no_for_in_array/no_for_in_array.go © LayerX Inc. 19

Slide 20

Slide 20 text

no-for-in-arrayの例 https://github.com/oxc-project/tsgolint/blob/v0.23.0/internal/rules/no_for_in_array/no_for_in_array.go © LayerX Inc. 20

Slide 21

Slide 21 text

https://github.com/oxc-project/tsgolint/tree/v0.23.0/internal/rules © LayerX Inc. 21

Slide 22

Slide 22 text

cmd/tsgolint/main.go でルールを登録している https://github.com/oxc-project/tsgolint/blob/v0.23.0/cmd/tsgolint/main.go#L162-L172 © LayerX Inc. 22

Slide 23

Slide 23 text

自分でもtype-awareなruleを入れてみたい!

Slide 24

Slide 24 text

どうやって入れる?

Slide 25

Slide 25 text

仮説 © LayerX Inc. Oxlintとtsgolintは別々に配布されている tsgolint側だけforkしてruleを足したら動く のでは? → Oxlintがどのようにtsgolintのバイナリを探すか調べた 25

Slide 26

Slide 26 text

Oxlintによるtsgolintバイナリの探索 https://github.com/oxc-project/oxc/blob/oxlint_v1.66.0/crates/oxc_linter/src/tsgolint.rs#L45-L48 © LayerX Inc. Oxlintにそれらしいコードを発見 26

Slide 27

Slide 27 text

Oxlintによるtsgolintバイナリの探索 https://github.com/oxc-project/oxc/blob/oxlint_v1.66.0/crates/oxc_linter/src/tsgolint.rs#L1259-L1266 © LayerX Inc. OXLINT_TSGOLINT_PATH 環境変数か、 node_modules/.bin からパスを入手していた 27

Slide 28

Slide 28 text

やったこと © LayerX Inc. tsgolintをforkし、独自のルールを追加 require-error-cause を足してみた 興味があれば: https://github.com/syumai/tsgolint-custom forkしたtsgolintをビルド OXLINT_TSGOLINT_PATH にビルドしたバイナリのパスを指定 Oxlintの設定で独自ルールを有効化、lintを実行 → 結果、何も検出されず失敗 28

Slide 29

Slide 29 text

なぜ失敗したのか?

Slide 30

Slide 30 text

補足: plugin ではないです (当時の勘違い) https://x.com/__syumai/status/2028114581714063731 © LayerX Inc. 30

Slide 31

Slide 31 text

Oxlint側のtsgolintルール定義 https://github.com/oxc-project/oxc/pull/19446 © LayerX Inc. prefer-read-only を見てみた 31

Slide 32

Slide 32 text

PRの変更ファイル一覧から、Oxlint側のtypescriptのrule定義一覧を発見 https://github.com/oxc-project/oxc/tree/56a7feb22fdfd82ea4e52a376cfcf3ca6f7388cd/crates/oxc_linter/src/rules/typescript © LayerX Inc. 32

Slide 33

Slide 33 text

prefer-readonly の定義の例 type-aware なルールは (tsgolint) の指定がある https://github.com/oxc-project/oxc/blob/oxlint_v1.66.0/crates/oxc_linter/src/rules/typescript/prefer_readonly.rs © LayerX Inc. 33

Slide 34

Slide 34 text

no-explicit-any の定義の例 type-aware でないルールは (tsgolint) の指定がない https://github.com/oxc-project/oxc/blob/oxlint_v1.66.0/crates/oxc_linter/src/rules/typescript/no_explicit_any.rs © LayerX Inc. 34

Slide 35

Slide 35 text

declare_oxc_lint マクロ マクロへの引数のパース時に (tsgolint) のmarkerを探して、 is_tsgolint_rule: true のルールとして登録 https://github.com/oxc-project/oxc/blob/oxlint_v1.66.0/crates/oxc_macros/src/declare_oxc_lint.rs#L79-L97 © LayerX Inc. 35

Slide 36

Slide 36 text

実行の流れ

Slide 37

Slide 37 text

実行の流れ © LayerX Inc. Oxlintを実行 lintルールの実行に進む 通常のルールは、Oxlint側で実行 is_tsgolint_rule が有効なルールは、Oxlint側で実行せずフォールバック type-aware lintingが有効な場合は、tsgolintを子プロセスとしてヘッドレスで起動 Oxlintの実行結果と、tsgolintの実行結果をまとめてfix / report 37

Slide 38

Slide 38 text

lintルール実行時の is_tsgolint_rule のフォールバック is_tsgolint_rule が有効なルールをskipする https://github.com/oxc-project/oxc/blob/oxlint_v1.66.0/crates/oxc_linter/src/lib.rs © LayerX Inc. 38

Slide 39

Slide 39 text

tsgolintのヘッドレスでの起動 tsgolintの実行パスを探して tsgolint headless を実行、stdin / stdoutを接続する © LayerX Inc. 39

Slide 40

Slide 40 text

Oxlint → tsgolintの通信処理 https://github.com/oxc-project/oxc/blob/oxlint_v1.66.0/crates/oxc_linter/src/tsgolint.rs © LayerX Inc. JSONでstdinに書き込む lint対象のファイルパス、使用するルールなどの情報を含んでいる 40

Slide 41

Slide 41 text

tsgolint → Oxlintの通信処理 https://github.com/oxc-project/oxc/blob/oxlint_v1.66.0/crates/oxc_linter/src/tsgolint.rs © LayerX Inc. lint結果のdiagnosticsをバイナリエンコードで返す Oxlint側の TsGoLintMessageStream でパースして、Oxlint側ルールの診断結果とまとめる 41

Slide 42

Slide 42 text

まとめ © LayerX Inc. tsgolintは、typescript-goの内部機能を使ってtype-awareなlintルールを実装している Oxlintから実行できるtype-awareなGo製のルールを簡単に追加する方法はない Oxlintとtsgolintの両方を変更 する必要がある Oxlintはtsgolintを子プロセスとして起動し、stdin / stdoutで通信している tsgolintへの入力はJSON、出力は独自のバイナリフォーマット 42