Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ts-morph実践:型を利用するcodemodのテクニック
Search
ypresto
May 24, 2025
Programming
1
900
ts-morph実践:型を利用するcodemodのテクニック
TSKaigi 2025
ypresto
May 24, 2025
Tweet
Share
More Decks by ypresto
See All by ypresto
Why React!?? Next.jsそしてReactを改めてイチから選ぶ
ypresto
12
4.9k
状態と共に暮らす:ステートフルへの挑戦
ypresto
3
2.2k
Next.jsとNuxtが混在? iframeでなんとかする!
ypresto
3
4k
Cancel Next.js Page Navigation: Full Throttle
ypresto
1
4k
Next.js のページ遷移を全力で止める
ypresto
15
11k
TypeScriptの型とパフォーマンス (TSKaigi 2024)
ypresto
22
8.2k
アクセシビリティとE2Eテスト
ypresto
0
140
VS Codeのプロセスモデルとデバッグ方法 - パフォーマンスと安定性を支えるアーキテクチャ
ypresto
1
540
TypeScriptの型定義をPRする技術
ypresto
1
800
Other Decks in Programming
See All in Programming
ゼロダウンタイムでミドルウェアの バージョンアップを実現した手法と課題
wind111
0
110
「正規表現をつくる」をつくる / make "make regex"
makenowjust
1
420
複数チーム並行開発下でのコード移行アプローチ ~手動 Codemod から「生成AI 活用」への進化
andpad
0
170
KoogではじめるAIエージェント開発
hiroaki404
1
480
Register is more than clipboard
satorunooshie
1
470
AIエージェントでのJava開発がはかどるMCPをAIを使って開発してみた / java mcp for jjug
kishida
4
640
Flutterアプリ運用の現場で役立った監視Tips 5選
ostk0069
1
450
JEP 496 と JEP 497 から学ぶ耐量子計算機暗号入門 / Learning Post-Quantum Crypto Basics from JEP 496 & 497
mackey0225
2
280
AsyncSequenceとAsyncStreamのプロポーザルを全部読む!!
s_shimotori
1
280
予防に勝る防御なし(2025年版) - 堅牢なコードを導く様々な設計のヒント / Growing Reliable Code PHP Conference Fukuoka 2025
twada
PRO
37
12k
Verilator + Rust + gRPC と Efinix の RISC-V でAIアクセラレータをAIで作ってる話 RTLを語る会(18) 2025/11/08
ryuz88
0
360
Kotlinで実装するCPU/GPU 「協調的」パフォーマンス管理
matuyuhi
0
410
Featured
See All Featured
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
192
56k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.6k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Product Roadmaps are Hard
iamctodd
PRO
55
12k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
How to Ace a Technical Interview
jacobian
280
24k
RailsConf 2023
tenderlove
30
1.3k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
Faster Mobile Websites
deanohume
310
31k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
285
14k
Transcript
ts-morph実践: 型を利用するcodemodの技巧 テクニック 2025/05/23:TSKaigi 2025 @ 東京・神田 ypresto (@yuya_presto)
ypresto © LayerX Inc. LayerX バクラク事業部 (2024-01〜) プロダクト開発部 債権債務チーム Software
Engineer TypeScriptへのコントリビュート歴あり 宣伝の時間なんてないので採用サイトを 2
CfP応募後に tsgoが発表された! Compiler APIが塞がる可能性・・・ © LayerX Inc. 3
終 制作・著作 LayerX ったかと思ったけど大丈夫かも!? 中の人の回答 © LayerX Inc. 4
codemod © LayerX Inc. AST (抽象構文木) を通して、機械的にコードを書き換える DOMツリーとHTMLの関係 = ASTとコードの関係、と考えると楽。
ASTのNodeを探して書き換えると、コードが書き換わる jscodeshift:Meta製 例えばMUIのアップグレードのための @mui/codemod で使われている ts-morph: 型が使える← 今日 TypeScript Compiler API をゴリゴリとwrapしたライブラリ 5
ts-morphを使う利点 jscodeshiftや、ラップされていないCompiler APIと比べて・・・ © LayerX Inc. node.findReferencesAsNodes() でエディタのように参照元を探せる node.getType() で型情報をチェックできる
getTypeNode() で型注釈もすぐ取れる node.replaceWithText("const foo = 1") のように、 AST Nodeを組み立てず文字列で書き込める => 楽で安全な書き換え 6
具体例1: consoleの呼び出しをloggerに書き換え あちこちにはびこる「とりあえずconsole.error(e)」を退治したい © LayerX Inc. 7
Find And Replaceだと不安がある理由 © LayerX Inc. console.error(e) → logger.caught(e) 8
© LayerX Inc. console.error(e) → logger.caught(e) / 実装 9
© LayerX Inc. console.error(e) → logger.caught(e) / 実装 10
© LayerX Inc. console.error(e) → logger.caught(e) / 実装 11
Cannot find name 'logger' sourceFile.organizeImports() せずにimportを足すのがむずい。 そもそもimport { A }
from B のAとBをASTで扱うのがめんどい。 © LayerX Inc. console.error(e) → logger.caught(e) 12
しゃーなしでヘルパー作りました しばらくしたら公開されます。 © LayerX Inc. 13
具体例2: noImplicitAny: false を倒したい © LayerX Inc. 14
具体例2: noImplicitAny: false を倒したい 理論上は可能 (たぶん) © LayerX Inc. 15
型注釈を自動でつけるには © LayerX Inc. noImplicitAny: false を倒したい 16
1. 引数に使われた型を集める © LayerX Inc. noImplicitAny: false を倒したい 17
2. 集めた型をこねて丸める Type Wideningがないと、 let foo = 1 に 2
が入らなくなります。 © LayerX Inc. noImplicitAny: false を倒したい 18
ts-morphもCompiler APIも、型を作る方法がない 全くないからしゃーなしでchecker.ts読んで拾ってきた。 © LayerX Inc. noImplicitAny: false を倒したい 19
実装 © LayerX Inc. noImplicitAny: false を倒したい 20
意外とできる © LayerX Inc. 21
おわり © LayerX Inc. ts-morphで型を使うと無限の可能性がある おもしろい悪事ができそう ASTの知識が必要 https://astexplorer.net/ を片手にやりましょう ヘルパーを用意して楽にしましょう
今日のコードはここに上げています https://github.com/ypresto/ts-morph-toybox あとでnpmへ 22
ここから先は喋らないやつ © LayerX Inc. 23
あと:AI来るともcodemod死せず codemodの弱点:ASTの知識が必要、書くのが大変 © LayerX Inc. AIは、プロジェクト全体をまとめて読めるわけじゃない (Context Window) codemodは、プロジェクト全体に決定論的に同じ内容を高速に当てら れる
なので、codemodは引き続き有効。できればAIに書かせたい。 24
例えばenabled: trueを全部の呼び出し元に追加したいとき © LayerX Inc. 25
メソッドチェーンの呼び出しを探す © LayerX Inc. { baz: () => { ...
} } のbazの呼び出しが、foo.bar.baz(1) になっていると き 愚直に祖先のcallを取ると、boo(foo.bar.baz) の boo() が取れてしまう ASTが読めると baz (Identifier) → foo.bar.baz (Property Access Expression) → foo.bar.baz(...) (Call Expression) とできる https://astexplorer.net/ を片手にやる 26
理解は容易、 実装は困難。 © LayerX Inc. 27