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
750
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
Capacitor製のWebViewアプリからReact Native製のハイブリッドアプリへ
yukukotani
4
940
Kuma UI が提唱する Hybrid Approach CSS-in-JS の仕組み
yukukotani
2
400
GraphQLスキーマ設計の勘所
yukukotani
39
16k
既存Webサービスのモバイルアプリ版を 1週間でリリースし、進化させてきた話
yukukotani
0
620
先を見据えたMVPのフロントエンド開発
yukukotani
0
260
Bundle Side Optimization in Future JavaScript - JSConf JP 2021
yukukotani
2
2.7k
Kotlin/JS の仕組み / How KotlinJS works
yukukotani
5
3k
Kotlin/JS イケイケフロントエンド開発 / Ikeike Frontend Development in KotlinJS
yukukotani
0
360
Other Decks in Technology
See All in Technology
エンジニアリングマネージャーはどう学んでいくのか #devsumi / How Do Engineering Managers Continue to Learn and Grow?
expajp
4
1.3k
AWSで”最小権限の原則”を実現するための考え方 /20240722-ssmjp-aws-least-privilege
opelab
10
4.4k
ABEMAにおけるLLMを用いたコンテンツベース推薦システム導入と効果検証
cyberagentdevelopers
PRO
1
760
ギークの理想が7つ集まるエムスリーで夢を叶えよう - エムスリー株式会社
m3_engineering
1
260
CTOから見た事業開発とプロダクト開発 / My Perspective on Business and Product Development as CTO
keisuke69
4
960
AOAI Dev Day LLMシステム開発 Tips集
hirosatogamo
15
3.8k
20240717_イケコパ代表Copilot_in_Teams会社でこう使ってます
ponponmikankan
2
430
VPoEの視点から見た、ヘンリーがサーバーサイドKotlinを使う理由 / Why Server-side Kotlin 2024
cho0o0
1
420
コミュニティサービスに「あなたへ」フィードを リリースするまでの試行錯誤
takapy
1
150
Android研修【MIXI 24新卒技術研修】
mixi_engineers
PRO
0
100
サービスの持続的な成長と技術負債について
siva_official
PRO
10
4.4k
Flutter研修【MIXI 24新卒技術研修】
mixi_engineers
PRO
0
160
Featured
See All Featured
Code Reviewing Like a Champion
maltzj
517
39k
Agile that works and the tools we love
rasmusluckow
325
20k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
34
1.9k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
24
1.8k
10 Git Anti Patterns You Should be Aware of
lemiorhan
652
58k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
44
4.7k
Design by the Numbers
sachag
277
18k
What's in a price? How to price your products and services
michaelherold
239
11k
Optimizing for Happiness
mojombo
373
69k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
360
22k
Web Components: a chance to create the future
zenorocha
307
41k
Building Adaptive Systems
keathley
34
2k
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のブースにいます!