Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ts-morph実践:型を利用するcodemodのテクニック
Search
ypresto
May 24, 2025
Programming
1
930
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
5k
状態と共に暮らす:ステートフルへの挑戦
ypresto
3
2.3k
Next.jsとNuxtが混在? iframeでなんとかする!
ypresto
3
4k
Cancel Next.js Page Navigation: Full Throttle
ypresto
1
4.1k
Next.js のページ遷移を全力で止める
ypresto
15
11k
TypeScriptの型とパフォーマンス (TSKaigi 2024)
ypresto
24
9.2k
アクセシビリティとE2Eテスト
ypresto
0
150
VS Codeのプロセスモデルとデバッグ方法 - パフォーマンスと安定性を支えるアーキテクチャ
ypresto
1
560
TypeScriptの型定義をPRする技術
ypresto
1
810
Other Decks in Programming
See All in Programming
CSC305 Lecture 17
javiergs
PRO
0
300
非同期処理の迷宮を抜ける: 初学者がつまづく構造的な原因
pd1xx
1
660
【CA.ai #3】ワークフローから見直すAIエージェント — 必要な場面と“選ばない”判断
satoaoaka
0
230
スタートアップを支える技術戦略と組織づくり
pospome
8
15k
「コードは上から下へ読むのが一番」と思った時に、思い出してほしい話
panda728
PRO
37
23k
これだけで丸わかり!LangChain v1.0 アップデートまとめ
os1ma
6
1.4k
DSPy Meetup Tokyo #1 - はじめてのDSPy
masahiro_nishimi
1
150
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
syumai
5
1.9k
モデル駆動設計をやってみようワークショップ開催報告(Modeling Forum2025) / model driven design workshop report
haru860
0
230
エディターってAIで操作できるんだぜ
kis9a
0
670
全員アーキテクトで挑む、 巨大で高密度なドメインの紐解き方
agatan
8
19k
バックエンドエンジニアによる Amebaブログ K8s 基盤への CronJobの導入・運用経験
sunabig
0
140
Featured
See All Featured
The Invisible Side of Design
smashingmag
302
51k
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
The Language of Interfaces
destraynor
162
25k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
36
6.2k
Agile that works and the tools we love
rasmusluckow
331
21k
The Power of CSS Pseudo Elements
geoffreycrofte
80
6.1k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
The Art of Programming - Codeland 2020
erikaheidi
56
14k
What's in a price? How to price your products and services
michaelherold
246
12k
Practical Orchestrator
shlominoach
190
11k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
1
88
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