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
ts-morph実践:型を利用するcodemodのテクニック
Search
ypresto
May 24, 2025
Programming
1.4k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ts-morph実践:型を利用するcodemodのテクニック
TSKaigi 2025
ypresto
May 24, 2025
More Decks by ypresto
See All by ypresto
TypeScriptはどのようにどこまで推論できるのか ─ とにかく as は禁止で
ypresto
3
1.3k
バクラク最古参プロダクトで重ねた技術投資を振り返る
ypresto
0
320
Why React!?? Next.jsそしてReactを改めてイチから選ぶ
ypresto
12
5.3k
状態と共に暮らす:ステートフルへの挑戦
ypresto
3
3k
Next.jsとNuxtが混在? iframeでなんとかする!
ypresto
3
4.6k
Cancel Next.js Page Navigation: Full Throttle
ypresto
1
5k
Next.js のページ遷移を全力で止める
ypresto
15
13k
TypeScriptの型とパフォーマンス (TSKaigi 2024)
ypresto
24
10k
アクセシビリティとE2Eテスト
ypresto
0
210
Other Decks in Programming
See All in Programming
SODA - FACT BOOK(EN)
sodainc
1
210
クラウドエージェントは、 何がそんなに便利なのか / what makes cloud agents so useful
rkaga
5
790
クラウドゲーミングのパフォーマンス最適化に挑む / Cloud Gaming Performance Tuning
vivion
0
330
Apple Intelligenceとオンデバイス時代の到来
yahir0
0
230
小さなアプリを作って公開するまで
onozaty
0
130
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
3
1.4k
Lambda durable functionsでHuman in the Loopを楽に…楽に……
har1101
2
290
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
3
1.7k
オーケストレーション記述言語 Katari
yukikurage
0
240
Coding with AI: How to trust the storyteller (AWS Community Day Adria, Ljubljana 2026)
slobodan
0
140
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
200
느린 네트워크와 저사양 디바이스 사용자를 위한 웹뷰 로딩 시간 개선기
kmkim
1
210
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
The Limits of Empathy - UXLibs8
cassininazir
2
770
Leo the Paperboy
mayatellez
10
2.4k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.4k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
320
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
820
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3.3k
Build your cross-platform service in a week with App Engine
jlugia
234
19k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1.1k
Claude Code のすすめ
schroneko
67
230k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
23k
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