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
800
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
10
3.7k
状態と共に暮らす:ステートフルへの挑戦
ypresto
3
2.1k
Next.jsとNuxtが混在? iframeでなんとかする!
ypresto
3
3.8k
Cancel Next.js Page Navigation: Full Throttle
ypresto
1
3.7k
Next.js のページ遷移を全力で止める
ypresto
15
9.9k
TypeScriptの型とパフォーマンス (TSKaigi 2024)
ypresto
22
8.1k
アクセシビリティとE2Eテスト
ypresto
0
140
VS Codeのプロセスモデルとデバッグ方法 - パフォーマンスと安定性を支えるアーキテクチャ
ypresto
1
530
TypeScriptの型定義をPRする技術
ypresto
1
780
Other Decks in Programming
See All in Programming
Introducing ReActionView: A new ActionView-Compatible ERB Engine @ Kaigi on Rails 2025, Tokyo, Japan
marcoroth
3
680
CSC305 Lecture 03
javiergs
PRO
0
220
Чего вы не знали о строках в Python – Василий Рябов, PythoNN
sobolevn
0
150
Web技術を最大限活用してRAW画像を現像する / Developing RAW Images on the Web
ssssota
2
1k
LLMとPlaywright/reg-suitを活用した jQueryリファクタリングの実際
kinocoboy2
4
650
クラシルを支える技術と組織
rakutek
0
190
Go Conference 2025: Goで体感するMultipath TCP ― Go 1.24 時代の MPTCP Listener を理解する
takehaya
7
1.4k
いま中途半端なSwift 6対応をするより、Default ActorやApproachable Concurrencyを有効にしてからでいいんじゃない?
yimajo
2
210
麻雀点数計算問題生成タスクから学ぶ Single Agentの限界と Agentic Workflowの底力
po3rin
5
2k
ABEMAモバイルアプリが Kotlin Multiplatformと歩んだ5年 ─ 導入と運用、成功と課題 / iOSDC 2025
akkyie
0
300
SpecKitでどこまでできる? コストはどれくらい?
leveragestech
0
380
プログラマのための作曲入門
cheebow
0
510
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
173
14k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.7k
Git: the NoSQL Database
bkeepers
PRO
431
66k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
45
2.5k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
Unsuck your backbone
ammeep
671
58k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
30
9.7k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
How STYLIGHT went responsive
nonsquared
100
5.8k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.5k
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