Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
Search
syumai
December 05, 2025
Programming
3.3k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
layerx.go #3 の発表資料です!
https://layerx.connpass.com/event/372984/
syumai
December 05, 2025
More Decks by syumai
See All by syumai
自分的「カンファレンスの楽しみ方」
syumai
0
210
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
3
1.5k
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.9k
Oxlintのカスタムルールの現況
syumai
6
2.1k
Oxlintはいかにしてtsgolintのlint ruleを呼び出しているのか
syumai
2
1.6k
『[入門] Cloudflare Workers』本はなぜ誕生したのか
syumai
0
600
知られているようで知られていない JavaScriptの仕様 4選
syumai
3
1.3k
CloudflareのSandbox SDKを試してみた
syumai
0
1.1k
実践AIチャットボットUI実装入門
syumai
9
4.6k
Other Decks in Programming
See All in Programming
海上で動くGoサーバー: goroutineとchannelでさばく航行データストリーム
atsuki_seo
0
730
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
150
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
180
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
250
Go × SIMDで高速化するベクトル検索 ~ルーフラインモデルでSIMDが効く境界を探れ! ~
po3rin
1
1.7k
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
5
3.3k
AHC070解法紹介
eijirou
0
120
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
370
AI活用は、個人から組織へ|マルチプレイヤーエージェントハーネス「QM」の社内活用事例 / AI use is moving from individuals to orgs
rkaga
1
110
Snowflakeで業務アプリを作ろう。 Snowflakeのアプリ機能解説&実践ガイド
ayumu_yamaguchi
1
280
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
120
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
440
Featured
See All Featured
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
68
57k
The browser strikes back
jonoalderson
0
1.7k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
700
Technical Leadership for Architectural Decision Making
baasie
3
570
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
450
Are puppies a ranking factor?
jonoalderson
2
3.9k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
240
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Transcript
tsgolintはいかにしてtypescript-goの 非公開APIを呼び出しているのか syumai layerx.go #3 (2025/12/5)
自己紹介 syumai LayerX所属 ソフトウェアエンジニア ECMAScript 仕様輪読会 / Asakusa.go 主催 Software
Design 2023年12月号から2025年2月号まで Cloudflare Workersの連載をしました Twitter (現𝕏): @__syumai Website: https://syum.ai
本日話すこと typescript-go (tsgo) とは tsgolintとは tsgolintからtsgoの非公開APIへのアクセス方法
typescript-go (tsgo) とは
typescript-go (tsgo) とは TypeScriptのGo実装 もともとTypeScript自身がTypeScriptで実装されている 型チェック、トランスパイルなどのロジックを持つ tsc コマンドを通して処理が行われる 処理の実行はJSにトランスパイルされた上でNode.js上などで行われる microsoft/typescript-go
リポジトリでは、TypeScriptのコアのロジックをGo で再実装している tsc コマンドを置き換える tsgo コマンドを提供 TypeScript 7 としてリリース予定
2025年3月に発表、界隈がざわついた https://devblogs.microsoft.com/typescript/typescript-native-port/
2025年12月に進捗報告があり、かなり安定してきているらしい https://devblogs.microsoft.com/typescript/typescript-native-port/
tsgoの特徴 とにかく速い tscの10倍の速度でビルドが完了することもあるらしい
tsgoの特徴 高い互換性 巨大な型チェックのロジックを持つ checker.ts を行単位でGoにポート checker.ts は5万行ほどのサイズ 巨大すぎて、再設計しての実装は現実的ではない Goが選ばれた理由は、文法的にそのまま移植しやすかったかららしい
tsgoの特徴 ロジックをライブラリ提供しない 型チェックなどのロジックを、tsgoコマンド経由でしか提供しない 実装は、全部 internal package配下にあり、ライブラリ提供を想定しない Launguage Serverや標準出力を使ったIPCベースのAPIサーバーは提供する IPCの仕様はまだ決まってなさそう
None
tsgolintとは
None
tsgolintとは 2025年7月に、typescript-eslintのチームがリリースしたtsgoベースのLinter https://github.com/typescript-eslint/tsgolint 実装は全部Go ESLint + typescript-eslintより20 ~ 40倍速いらしい tsgoのinternal
packageの中身を無理矢理公開して使っている あくまで実験的なプロジェクトで、typescript-eslintの置き換えを意図しない
tsgolintを取り巻く状況 typescript-eslintのチームはもうメンテしていない oxcのチームがforkし、oxlintのtype-aware lintingに使っている こっちはかなりアクティブにメンテされている https://github.com/oxc-project/tsgolint
tsgolintからのtsgoの非公開API呼び出し方法
tsgolintからのtsgoの非公開API呼び出し方法 注: まだ調べ途中なので、不正確な情報があるかもしれません
その1: git submoduleによるtypescript-goの設置
その1: git submoduleによるtypescript-goの設置 git submoduleで typescript-go のリポジトリを丸ごと tsgolint リポジトリ直 下に置いている
go get しないことで自由度を上げている (コード生成、パッチ当てなど) submoduleを明示的に更新しないと壊れない (Go Modulesで管理するとうっかり上がることがあるかもしれない?) . ├── cmd │ └── tsgolint ├── go.mod ├── go.sum ├── go.work ├── go.work.sum ├── internal ├── README.md └── typescript-go
Workspaceでtypescript-go moduleを追加 go.work で typescript-go ディレクトリを指定 github.com/microsoft/typescript-go moduleが相対パスで取得可能に go 1.24.1
use ( . ./typescript-go )
その2: go:linkname
internal packageにlinkするための shim package tsgolint 直下に shim packageを設置 中身は typescript-go
の internal package配下に対応 公開したいものがここに置かれる ./shim ├── ast ├── bundled ├── checker ├── compiler ├── core ├── scanner ├── tsoptions ├── tspath └── vfs
shimファイルの中身 (例) 例は shim/ast/shim.go internalな型をそのままexportしている // Code generated by tools/gen_shims.
DO NOT EDIT. package ast import "github.com/microsoft/typescript-go/internal/ast" /* 中略 */ type AccessExpression = ast.AccessExpression type AccessorDeclaration = ast.AccessorDeclaration
shimファイルの中身 (例) 同じく shim/ast/shim.go の例 関数はbody無しで、 go:linkname でlinkしてexportしている github.com/microsoft/typescript-go/shim/ast/shim/ast.CanHaveDecorators を呼んだら、
github.com/microsoft/typescript-go/internal/ast.CanHaveDecorators のロ ジックが呼ばれる構造 //go:linkname CanHaveDecorators github.com/microsoft/typescript-go/internal/ast.CanHaveDecorators func CanHaveDecorators(node *ast.Node) bool //go:linkname CanHaveIllegalDecorators github.com/microsoft/typescript-go/internal/ast.CanHaveIllegalDecorators func CanHaveIllegalDecorators(node *ast.Node) bool //go:linkname CanHaveIllegalModifiers github.com/microsoft/typescript-go/internal/ast.CanHaveIllegalModifiers func CanHaveIllegalModifiers(node *ast.Node) bool //go:linkname CanHaveModifiers github.com/microsoft/typescript-go/internal/ast.CanHaveModifiers func CanHaveModifiers(node *ast.Node) bool
shimファイルの中身 (例) shim/checker/shim.go の例 非公開メソッドも go:linkname を駆使して公開している type Checker =
checker.Checker //go:linkname Checker_getResolvedSignature github.com/microsoft/typescript-go/internal/checker.(*Checker).getResolvedSignature func Checker_getResolvedSignature(recv *checker.Checker, node *ast.Node, candidatesOutArray *[]*checker.Signature, checkMode checker.CheckMode) *checker.Signature //go:linkname Checker_getTypeOfSymbol github.com/microsoft/typescript-go/internal/checker.(*Checker).getTypeOfSymbol func Checker_getTypeOfSymbol(recv *checker.Checker, symbol *ast.Symbol) *checker.Type わかりやすさのために改行していますが、実際は改行なしです
go:linkname って非推奨じゃなかった? Goのランタイムへの go:linkname が封じられただけで、サードパーティーの moduleに対しては普通に使える runtime packageなどへの go:linkname はNG
github.com/microsoft/typescript-go への go:linkname は何も問題ない 詳しい経緯はANDPADさんの「Go界隈で巻き起こった go:linkname 騒動につい て」を参照ください https://tech.andpad.co.jp/entry/2024/06/20/140000
実際の呼び出し例 internal/rules/no_confusing_void_expression/no_confusing_void_expression.go shimが無いと呼び出せない機能でlintルールを実装 package no_confusing_void_expression import ( "github.com/microsoft/typescript-go/shim/ast" "github.com/microsoft/typescript-go/shim/checker" "github.com/microsoft/typescript-go/shim/scanner"
"github.com/typescript-eslint/tsgolint/internal/rule" "github.com/typescript-eslint/tsgolint/internal/utils" ) /* 中略 */ return utils.Some(callSignatures, func(s *checker.Signature) bool { returnType := checker.Checker_getReturnTypeOfSignature(ctx.TypeChecker, s) return utils.Some(utils.UnionTypeParts(returnType), utils.IsIntrinsicVoidType) })
その3: Go Moduleのreplaceで shim を typescript-go の中に入れる
Go Moduleのreplaceで shim を typescript-go の中に入れる go.mod の例 module github.com/typescript-eslint/tsgolint
go 1.24.1 replace ( github.com/microsoft/typescript-go/shim/ast => ./shim/ast github.com/microsoft/typescript-go/shim/bundled => ./shim/bundled github.com/microsoft/typescript-go/shim/checker => ./shim/checker github.com/microsoft/typescript-go/shim/compiler => ./shim/compiler github.com/microsoft/typescript-go/shim/core => ./shim/core github.com/microsoft/typescript-go/shim/scanner => ./shim/scanner github.com/microsoft/typescript-go/shim/tsoptions => ./shim/tsoptions github.com/microsoft/typescript-go/shim/tspath => ./shim/tspath github.com/microsoft/typescript-go/shim/vfs => ./shim/vfs github.com/microsoft/typescript-go/shim/vfs/cachedvfs => ./shim/vfs/cachedvfs github.com/microsoft/typescript-go/shim/vfs/osvfs => ./shim/vfs/osvfs )
なぜ shim を typescript-go に入れる必要があるのか? 恐らく internal package配下の型情報をexportするのが主目的 shim が
typescript-go 内なので typescript-go の internal が見える go:linkname での関数の公開にも、引数・戻り値の型情報は必要 さっきの shim/ast/shim.go の例 // Code generated by tools/gen_shims. DO NOT EDIT. package ast import "github.com/microsoft/typescript-go/internal/ast" /* 中略 */ type AccessExpression = ast.AccessExpression type AccessorDeclaration = ast.AccessorDeclaration
その4: shim の生成
shim の生成 tools/gen_shims で実装されている ASTを解析して、 internal package配下で公開の型・関数を自動で shim にexport 非公開のメソッド、関数などのexportに使える
extra-shim.json という設 定ファイルもある 手間のかかるexportの作業を全自動化している 実装の詳細は見れてないです
その他のテクニック unsafe.Pointer を駆使して構造体の非公開フィールドを公開してそう やむを得ずtypescript-go本体にパッチを当ててる部分もある様子 patches ディレクトリに入っている
まとめ tsgolintは、あらゆる方法を駆使してtypescript-goの非公開APIを公開している go:linkname Go Modulesのreplace shimの自動生成 どうしても、外部のGo製ライブラリの非公開APIを使いたくなってしまった時に参 考になるかも どう考えても壊れやすい仕組みではあるので、覚悟を決めないと難しそうな 印象
ご清聴ありがとうございました!