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
Real World Type Puzzle and Code Generation
Search
Yuku Kotani
May 11, 2024
Technology
4
950
Real World Type Puzzle and Code Generation
TSKaigi 2024
https://tskaigi.org/
Yuku Kotani
May 11, 2024
Tweet
Share
More Decks by Yuku Kotani
See All by Yuku Kotani
MCPとデザインシステムに立脚したデザインと実装の融合
yukukotani
1
830
Scale out your Claude Code ~自社専用Agentで10xする開発プロセス~
yukukotani
9
2.7k
AI Coding Agent Enablement in TypeScript
yukukotani
19
12k
AI Coding Agent Enablement - エージェントを自走させよう
yukukotani
14
7.6k
Expoによるアプリ開発の現在地とReact Server Componentsが切り開く未来
yukukotani
3
580
React 19でお手軽にCSS-in-JSを自作する
yukukotani
5
850
僕が思い描くTypeScriptの未来を勝手に先取りする
yukukotani
12
3.3k
Web技術を駆使してユーザーの画面を「録画」する
yukukotani
14
7.8k
Capacitor製のWebViewアプリからReact Native製のハイブリッドアプリへ
yukukotani
5
1.7k
Other Decks in Technology
See All in Technology
ライブサービスゲームQAのパフォーマンス検証による品質改善の取り組み
gree_tech
PRO
0
410
Snowflakeの生成AI機能を活用したデータ分析アプリの作成 〜Cortex AnalystとCortex Searchの活用とStreamlitアプリでの利用〜
nayuts
0
120
コスト削減の基本の「キ」~ コスト消費3大リソースへの対策 ~
smt7174
2
310
ガチな登山用デバイスからこんにちは
halka
1
190
AWS環境のリソース調査を Claude Code で効率化 / aws investigate with cc devio2025
masahirokawahara
2
970
AI エージェントとはそもそも何か? - 技術背景から Amazon Bedrock AgentCore での実装まで- / AI Agent Unicorn Day 2025
hariby
1
290
実践AIガバナンス
asei
3
270
「守る」から「進化させる」セキュリティへ ~AWS re:Inforce 2025参加報告~ / AWS re:Inforce 2025 Participation Report
yuj1osm
1
180
「魔法少女まどか☆マギカ Magia Exedra」のグローバル展開を支える、開発チームと翻訳チームの「意識しない協創」を実現するローカライズシステム
gree_tech
PRO
0
420
人と組織に偏重したEMへのアンチテーゼ──なぜ、EMに設計力が必要なのか/An antithesis to the overemphasis of people and organizations in EM
dskst
7
840
「魔法少女まどか☆マギカ Magia Exedra」での負荷試験の実践と学び
gree_tech
PRO
0
420
Product Management Conference -AI時代に進化するPdM-
kojima111
0
270
Featured
See All Featured
Into the Great Unknown - MozCon
thekraken
40
2k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
For a Future-Friendly Web
brad_frost
179
9.9k
The Invisible Side of Design
smashingmag
301
51k
Done Done
chrislema
185
16k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Embracing the Ebb and Flow
colly
87
4.8k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
8
910
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
31
2.2k
GitHub's CSS Performance
jonrohan
1032
460k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.6k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
36
2.5k
Transcript
Real World and Type Puzzle Code Generation @yukukotani 2024/05/11 -
TSKaigi 2024
小谷 優空 - @yukukotani ・Software Engineer @ Ubie, Inc. (2019/05~)
・Lead Architect ・Maintainer of Kuma UI ・Student @ Univ. Tsukuba (2019/04~) ・情報科学類 自己紹介
趣旨 型安全なコードを吐くコードジェネレータを作る野暮用があった(あるある) → 型安全 + コードジェネレータ = → 観察してエッセンスを抽出しよう! Prisma
観察するスキーマ このスキーマから生成されるコードを観察する User と Post がリレーションを持つ簡単なやつ
型パズルでselectした値に型をつける
None
None
簡略化した実装を観察する これが動くPrismaClient型(findFirst関数)の実装 スキーマに即した型がつく TS Playground
PrismaClient型 実際はクラスとして実装されているが、ここではシンプルなオブジェクト型に
入力の型を得る Type Argument Inferenceによって 型引数Tが推論される
入力の型を得る 型引数の制約は入力時の補完・エラー用。 GetSelectIncludeResultの導出には 条件型を使うので無関係
入力の型を得る 型引数の制約は入力時の補完・エラー用。 GetSelectIncludeResultの導出には 条件型を使うので無関係
出力の型を導出する 続いて出力の型を組成する要素を見ていく
$XxxPayload型 スキーマのモデルと対応して生成される カラムの型や他モデルとのリレーションを表現 → select結果の型を決定するための マスタとして機能 schema.prisma 生成される型
出力の型を導出する 第2型引数には入力の型をそのまま渡す
出力の型を導出する いよいよ出力の型そのものを見ていく
GetSelectIncludeResult<P, A> 事前生成のPayload型(P)とユーザーが渡す引数(A)から、select結果の型を導出
GetSelectIncludeResult<P, A> 条件型 `T extends { foo: infer S }
? S : never`パターンで、selectした中身を取る
GetSelectIncludeResult<P, A> Mapped Types で型を組み立てる
GetSelectIncludeResult<P, A> selectしたキーを Mapped Types のキーとする
GetSelectIncludeResult<P, A> キーに対応する値がfalse等の場合はneverにキャストして除外 Mapped Typesのキーを neverにすると丸ごと消える
GetSelectIncludeResult<P, A> Mapped Typesの値側を見ていく
GetSelectIncludeResult<P, A> Payload型を参照して、selectする値の型を取る
おさらい:$XxxPayload型 select結果の型を決定するためのマスタ schema.prisma 生成される型
GetSelectIncludeResult<P, A> scalarsではなくobjectsの場合も同様に取り、再帰的にselect結果を導出
GetSelectIncludeResult<P, A> 条件型に当てはまらなければneverに落とすが、最初の型制約で先に落ちるはず
まとめ:型パズルのエッセンス 型パズルを要素分解すると組み立てやすq Uf 型引数の推論によって入力の型を得 Df 型引数の制約を につけ E インターナルな型引数は補完不要なので頑張らなくて良q Bf
入力の型を条件型で絞り込みながら出力の型を組み立て E 事前生成したマスタ型(Payload)を参照してシンプル化 入力時の補完・エラーのため
型パズルをできるだけ頑張らない
なるべく事前生成して型計算を避ける Payload型から型パズルで導出できそうだが 重複を許容してすべて静的にコード生成する
なるべく事前生成して型計算を避ける モデルの一般化もせず重複生成
なるべく事前生成して型計算を避ける 事前生成ファイルは基本編集しないので、パースコストの影響が限定的 → ファイルサイズが大きくなってもOK 型チェックはfindFirstとかを触るたびに発生する(tsc内部でキャッシュは効くが) → パフォーマンスがDXに直撃する さらにビルド時間でもパースに比べて型チェックのほうが影響が大きい prisma/prisma の
tsc trace パース時間 型チェック時間
なるべく事前生成して型計算を避ける リアルタイムな入力に対してフィードバックしたい部分に絞って型計算をする その他はできるだけ静的にコード生成する
コード生成もできるだけ頑張らない
None
None
コード生成するコードは基本的につらい テンプレートリテラルなりASTビルダなりで組み立てるので見通しは最悪 なるべく生成するパターンを減らしたい
ライブラリとして切り出す 生成するコードのうち静的な部分はライブラリに切り出して、 生成コードからは参照するだけ 生成したコード
ライブラリとして切り出す Tips: ライブラリ内で使っているinternalな型もすべてexportする exportしていないと、この型を参照する他パッケージの.d.tsに インライン化されて爆発する Ref: https://github.com/prisma/prisma/blob/main /packages/client/src/runtime/core/types/exported/README.md
型以外は生成しない 生成された .d.ts 3500行に対して .js は200行程度 コード生成で頑張るのではなく Proxy を使った動的操作をしている
まとめ H リアルタイムな入力にフィードバックしたい部分だけは型パズルを頑張5 H 型パズルを要素分解して順番に考えるとやりやすF H それ以外はコードの重複を許容して事前生成に振り切5 H 完全に静的な型は生成すらせずライブラリÆ H
型以外のランタイム処理はProxyで頑張る
Thanks! Ubieのブースにいます!