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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
syumai
December 05, 2025
Programming
3.4k
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
Workers Cache を知る
syumai
0
400
自分的「カンファレンスの楽しみ方」
syumai
0
220
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
3
1.6k
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
2.2k
Oxlintのカスタムルールの現況
syumai
6
2.2k
Oxlintはいかにしてtsgolintのlint ruleを呼び出しているのか
syumai
2
1.7k
『[入門] Cloudflare Workers』本はなぜ誕生したのか
syumai
0
670
知られているようで知られていない JavaScriptの仕様 4選
syumai
3
1.3k
CloudflareのSandbox SDKを試してみた
syumai
0
1.2k
Other Decks in Programming
See All in Programming
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
240
HTML-in-Canvasで作る未来のWeb UI表現
clockmaker
5
6k
LLM 101
dalinaum
0
350
TanStack Vue Query と Pinia Colada から学ぶ非同期状態の型設計
aoshi
0
430
Performance Optimization With LLMs
xleitix
0
230
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
220
Vue.jsで作る空間解析アプリとCapacitorプラグインのData Bridge
hal_spidernight
1
130
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
250
AI Augmentation Techniques with Liberty
ivargrimstad
0
170
SFCで実現する病院・医療システムの動的組み立て式UI
koukimiura
1
140
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
210
Modernizing iOS Apps
seyfoyun
0
140
Featured
See All Featured
Java REST API Framework Comparison - PWX 2021
mraible
34
9.8k
From π to Pie charts
rasagy
1
420
We Are The Robots
honzajavorek
0
410
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
780
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
510
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
650
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
The browser strikes back
jonoalderson
0
1.9k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1.1k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
430
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
550
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.7k
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を使いたくなってしまった時に参 考になるかも どう考えても壊れやすい仕組みではあるので、覚悟を決めないと難しそうな 印象
ご清聴ありがとうございました!