Upgrade to Pro — share decks privately, control downloads, hide ads and more …

次世代リンターで探る、tsgo 時代における型認識カスタムルールの現実解

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

次世代リンターで探る、tsgo 時代における型認識カスタムルールの現実解

■ 登壇イベント
TSKaigi 2026
https://2026.tskaigi.org/talks/65

■PoCリポジトリ
https://github.com/YTakahashii/typed-lint-go-backend-poc

Avatar for Yuta Takahashi

Yuta Takahashi

May 22, 2026

More Decks by Yuta Takahashi

Other Decks in Programming

Transcript

  1. 2 ⾃⼰紹介:髙橋 佑太 / Yuta Takahashi • 株式会社メドレー 医科診療所プロダクト開発室 AI推進グループ

    テックリード ◦ クラウド診療システムCLINICSを開発 • TypeScript歴8年ほど ◦ TSは主にWebフロントエンドで利⽤ • Go/Rust の実務経験なし X: @Wakekupsloth Zenn: https://zenn.dev/yuta_takahashi はじめに
  2. 7 現在の型認識リントは typescript-eslint が担う typescript-eslint の型認識ルール: • ESLint プラグインとして JS

    / TS で書く • 必要なときだけ parser services 経由で TypeChecker を引いて型情報をもとに診断 • AST だけで動くリントより実⾏時間は伸びやすい 1. 導⼊: 型認識カスタムルールとは
  3. 9 typescript-go / tsgo • TypeScript コンパイラの Go / native

    実装 • 型チェック‧ビルド‧エディタ向け処理を⾼速化する取り組み(10x faster) • TypeScript 7.0 Beta として公開されており既に利⽤可能 ◦ `npm install -D @typescript/native-preview@beta` 2. tsgo 時代の変化
  4. 10 tsgo では型情報へのアクセス境界が変わる • 型チェック本体は Go 実装 / ネイティブプロセス側へ移る •

    JS / TS で書かれたESLintカスタムルールは、従来の parser services 経由では tsgo 側の型情報を参 照できない 2. tsgo 時代の変化
  5. 11 tsgo 時代の問い: 型認識カスタムルールをどこで動かすのか 1. 既存の typescript-eslint に残す ◦ JS

    版 TypeScript Compiler API をtsgoと併⽤で使い続ける ▪ npm install -D typescript@npm:@typescript/typescript6 ◦ 既存の配布‧設定‧エディタ統合を使える 2. Goやその他の型解析基盤の可能性 ◦ tsgo によって型チェック本体が Go バックエンドへ移るなら、型認識カスタムルールも Goで運⽤できる可能性がある ◦ 次世代リンターはJS 版 TypeScript Compiler APIに依存しない 型認識ルールに取り組んでいる ◦ 実⾏速度の⾯で恩恵を受けることができることがモチベーション 2. tsgo 時代の変化
  6. 13 Oxlint:tsgolint をバックエンドにして型認識リントに対応 • 構成: Rust 製 CLI + tsgolint

    • 型解析基盤: typescript-go(`oxc-project/tsgolint` 経由) • 標準の型認識ルール: @typescript-eslint 互換の型認識ルールを59件持つ • 型認識カスタムルール: 未対応 3. 型認識カスタムルールの実⾏基盤⽐較 https://oxc.rs/
  7. 14 Rslint :Go 製リンターとして型認識リントに対応 • 構成: `typescript-eslint/tsgolint` fork の Go

    製CLI • 型解析基盤: `typescript-go`(直接組み込み) • 標準の型認識ルール: @typescript-eslint 互換の型認識ルールを129件持つ • カスタムルール: 未対応 • 型認識カスタムルール: 未対応 3. 型認識カスタムルールの実⾏基盤⽐較 https://rslint.rs/
  8. 15 Biome:独⾃型推論で型認識リントに対応 • 構成: Rust製 CLI • 型解析基盤: Biotype(独⾃型推論) •

    標準の型認識ルール: `types` domain の16ルール • カスタムルール: GritQL プラグイン • 型認識カスタムルール: ⾮対応 3. 型認識カスタムルールの実⾏基盤⽐較 https://biomejs.dev/
  9. 16 型認識リントの対応状況 凡例: ◦ 安定提供 / △ 部分対応‧整備中 / ×

    現⾏の公開 API では不可 3. 型認識カスタムルールの実⾏基盤⽐較 実⾏基盤 標準の型認識ルール 型認識カスタム ルール 型解析基盤 typescript-eslint ◦ 133件 ◦ 対応 TypeScript Compiler API (JS 版) Oxlint + tsgolint △ `@typescript-eslint` 型認識 ルール 59件実装済み × ⾮対応 typescript-go(tsgolint 経由) Rslint △ 129件(内97件が完全実装済み) × ⾮対応 typescript-go(直接組み込み) Biome △ `types` domain 16 件(安定推 奨外) × ⾮対応 Biotype(独⾃型推論)
  10. 19 Rslint にパッチを当てて型認識カスタムルールを実装する PoC で確かめること: • 型認識カスタムルールをGo バックエンドルールとして「書けるか」 実装⽅針: •

    Rslint 本体に Go で組み込む • Rslint は git submodule で取り込み、PoC 差分は patch として管理 • patchしたRslintをビルドして実⾏ 検証リポジトリ: https://github.com/YTakahashii/typed-lint-go-backend-poc 4. Go バックエンドルール PoC
  11. 21 no-discarded-contract-value の実装構造 段階 1. 型判定 • 対象の式の型を取り、`Promise<T>` や `await`

    後の `T` を取り出して、 その `T` が契約型に該当するかを判断。 段階 2. 値のハンドリング判定 4. Go バックエンドルール PoC コード PoC 判定 `await cancelOrder(id)` NG (捨てている) `void await cancelOrder(id)` NG (明⽰的に捨てている) `return cancelOrder(id)` OK (呼び出し元へ渡す) `const result = await cancelOrder(id)` OK (保持)
  12. 27 運⽤モデルの差: 書けるだけでは代替できない 5. PoC の解釈と運⽤リスク 観点 ESLint プラグイン Go

    バックエンドルール プラグイン合成 設定に複数のプラグインを宣⾔して並⾏運⽤で きる 単⼀バイナリのみ。プラグイン合成モデルはな い 型 API 安定性 TypeScript Compiler API / parser services に依 存 typescript-go の internal API に依存 API 追従 typescript-eslint 側が吸収 バックエンド API の変化を⾃前 shim で追従 エディタ統合 既存経路(VSCode の eslint extension など)を 利⽤できる 専⽤バイナリをエディタ体験へ組み込む設計が 別に要る Goバックエンドでのカスタムルール⾃前実装は 運⽤負荷が⾮常に⾼い
  13. 28 運⽤リスク補⾜: internal API 依存 PoC は typescript-go の internal

    API に依存: • `GetAwaitedType` などの unexported api は shim で呼び出している • 内部実装の変更を⾃前で追従し続ける必要がある Go バックエンドルールを採⽤するなら、この追従コストを織り込んだ運⽤設計が必要。 5. PoC の解釈と運⽤リスク
  14. 31 PoC 題材の再設計: 型判定から API 規約へ PoC では型情報を⽤いて判定(再掲): 6. 現実解:

    振り分けと設計での削減 プロジェクト固有の型ルールをAPI規約に落とし込めないか考える
  15. 32 PoC 題材の再設計: 型判定から API 規約へ AST に出す 3 つの規約:

    • import パス / ファイル名で API 境界を識別する • 消費関数で扱い⽅を固定する(TypeScriptの型で縛る) • ファクトリ関数で インタフェースを強制する • 6. 現実解: 振り分けと設計での削減
  16. 33 PoC 題材の再設計: 型判定から API 規約へ AST に出す 3 つの規約:

    • import パス / ファイル名で API 境界を識別する • 消費関数で扱い⽅を固定する(TypeScriptの型で縛る) • ファクトリ関数で インタフェースを強制する 6. 現実解: 振り分けと設計での削減
  17. 36 TypeScript API 側の動向: programmatic API • 7.0 Beta 時点:

    安定 API は未提供。早くても 7.1 以降 • Node.js プログラムから別プロセスの `tsgo --api` に stdio / IPC で問い合わせる構成 7. 注視していきたい動向とまとめ
  18. 37 次世代リンターのカスタムプラグインの動向 7. 注視していきたい動向とまとめ リンター 型解析基盤 拡張 API の現状 /

    構想 Oxlint typescript-go(tsgolint 経由) JS プラグインは型情報未対応。Wasm プラグインは GitHub Discussion 上で議論中 Rslint typescript-go(直接組み込み) カスタムルールの公開‧配布モデルは未対応。 AST + 型公開 / AST のみ / 本体組み込みが議論中 Biome Biotype(独⾃型推論) GritQL プラグインは型情報⾮対応。RFC #1762 では、 GritQL で絞り込んだノードに対し JS / TS 層から Biotype の型 API を呼べるハイブリッドプラグインが議論中
  19. 38 ubugeeei/corsa-bind: Oxlint JS Plugin から tsgo へアクセスする試み 7. 注視していきたい動向とまとめ

    • Oxlint JS Plugin から `tsgo` の型情報へ問い合わせを実証したOSS • JS / TS で カスタム型認識ルールを 書くことができる • `@corsa-bind/napi` が Node.js から Rust 製 native addon を呼ぶ • Rust 側が `tsgo --api` を起動し、stdio で型情報を問い合わせる Oxlint JS Pluginからtsgoへアクセスする仕組みの概要
  20. 39 ubugeeei/corsa-bind: Oxlint JS Plugin から tsgo へアクセスする試み 7. 注視していきたい動向とまとめ

    • 馴染みあるparser services / TypeChecker API でカスタ ムルールを記述する例 (https://github.com/ubugeeei/corsa-bind#type-awar e-oxlint 出典)
  21. 40 まとめ: 型認識ルールは 3 つの選択肢に振り分ける 現時点での答えは、まず標準の型認識ルールで⾜りるかを⾒ること。 残った型認識カスタムルールは、段階的に振り分ける: • 設計で型認識カスタムルールを不要にする (型設計で表す

    / 現状の AST だけで判定する / API 設計を変えて AST に表す) • 既存の typescript-eslint に残す (速度要件がない場合は最も安定の選択肢) • 速度優先で Go 専⽤バイナリ運⽤へ (速度がボトルネック、かつ API 整備を待てない領域) エコシステムの進化を注視しつつ 特に新規開発で型認識カスタムルールが欲しくなった際は⼀度⽴ち⽌まり、 API 設計で解決できないかを考えたい。 7. 注視していきたい動向とまとめ
  22. 42 ⼀次情報: TypeScript / tsgo API - TypeScript 7.0 Beta

    公式ブログ https://devblogs.microsoft.com/typescript/announcing-typescript-7-0-beta/ - TypeScript Native Preview 公式ブログ https://devblogs.microsoft.com/typescript/announcing-typescript-native-previews/ - `microsoft/typescript-go` repository https://github.com/microsoft/typescript-go - `microsoft/typescript-go` API の⾻格を⽰す PR https://github.com/microsoft/typescript-go/pull/711 Appendix
  23. 43 ⼀次情報: typescript-eslint - typescript-eslint Rules 公式ドキュメント https://typescript-eslint.io/rules/ - typescript-eslint

    Typed Rules 公式ドキュメント https://typescript-eslint.io/developers/custom-rules/#typed-rules - `typescript-eslint/no-floating-promises` 公式ドキュメント https://typescript-eslint.io/rules/no-floating-promises/ Appendix
  24. 44 ⼀次情報: Oxlint - Oxlint Type-Aware Linting 公式ドキュメント https://oxc.rs/docs/guide/usage/linter/type-aware.html -

    Oxlint Type-Aware Linting Alpha 公式ブログ https://oxc.rs/blog/2025-12-08-type-aware-alpha.html - `oxc-project/tsgolint` repository https://github.com/oxc-project/tsgolint - `oxc-project/tsgolint` Architecture https://github.com/oxc-project/tsgolint/blob/main/ARCHITECTURE.md - `oxc-project/tsgolint` Benchmarks https://github.com/oxc-project/tsgolint/blob/main/benchmarks/README.md Appendix
  25. 45 ⼀次情報: Oxlint - Oxlint JS Plugins 公式ドキュメント https://oxc.rs/docs/guide/usage/linter/js-plugins -

    Oxlint Writing JS Plugins 公式ドキュメント https://oxc.rs/docs/guide/usage/linter/writing-js-plugins - Oxc GitHub Discussion: Oxlint Plugins Written In JavaScript(Wasm プラグイン検討コメントを含む) https://github.com/oxc-project/oxc/discussions/10342 - Oxc GitHub Discussion: Oxlint Custom JS Plugins ESLint Compat https://github.com/oxc-project/oxc/discussions/14862 - Oxc GitHub Discussion: Oxlint JS Plugins compatibility https://github.com/oxc-project/oxc/discussions/20245 Appendix
  26. 46 ⼀次情報: Rslint - `web-infra-dev/rslint` repository https://github.com/web-infra-dev/rslint - Rslint `@typescript-eslint`

    互換ルール⼀覧 https://rslint.rs/rules/?group=%40typescript-eslint - `web-infra-dev/rslint` issue: Rslint Custom Rule Support https://github.com/web-infra-dev/rslint/issues/32 Appendix
  27. 47 ⼀次情報: Biome v2 / Biotype - Biome v2 —

    codename: Biotype(公式ブログ) https://biomejs.dev/blog/biome-v2/ - Biome v2.0 beta(公式ブログ) https://biomejs.dev/blog/biome-v2-0-beta/ - Biome v2.1(公式ブログ‧noFloatingPromises ~85% ⾔及) https://biomejs.dev/blog/biome-v2-1/ - Biome partners with Vercel to improve type inference(公式ブログ) https://biomejs.dev/blog/vercel-partners-biome-type-inference/ - Roadmap 2025 and Biome 2.0(公式ブログ) https://biomejs.dev/blog/roadmap-2025/ Appendix
  28. 48 ⼀次情報: Biome v2 / Biotype - Biome Linter Domains

    公式ドキュメント https://biomejs.dev/linter/domains/ - Biome Linter Plugins 公式ドキュメント https://biomejs.dev/linter/plugins/ - Biome GritQL 公式リファレンス https://biomejs.dev/reference/gritql/ - Biome GitHub Discussion: RFC: Biome Plugins Proposal https://github.com/biomejs/biome/discussions/1762 Appendix
  29. 49 ⼀次情報: corsa-bind - `ubugeeei/corsa-bind` repository https://github.com/ubugeeei/corsa-bind - `corsa-bind` README(`@corsa-bind/napi`

    と `corsa-oxlint` の位置づけ) https://github.com/ubugeeei/corsa-bind#type-aware-oxlint - `corsa-oxlint` package README https://github.com/ubugeeei/corsa-bind/tree/main/src/bindings/nodejs/typescript_oxlint Appendix