$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
僕が思い描くTypeScriptの未来を勝手に先取りする
Search
Yuku Kotani
September 06, 2024
Programming
11
2.9k
僕が思い描くTypeScriptの未来を勝手に先取りする
Web Developer Conference 2024
https://web-study.connpass.com/event/321711/
Yuku Kotani
September 06, 2024
Tweet
Share
More Decks by Yuku Kotani
See All by Yuku Kotani
Web技術を駆使してユーザーの画面を「録画」する
yukukotani
14
7.1k
Capacitor製のWebViewアプリからReact Native製のハイブリッドアプリへ
yukukotani
5
1.3k
Real World Type Puzzle and Code Generation
yukukotani
4
840
Kuma UI が提唱する Hybrid Approach CSS-in-JS の仕組み
yukukotani
2
500
GraphQLスキーマ設計の勘所
yukukotani
42
17k
既存Webサービスのモバイルアプリ版を 1週間でリリースし、進化させてきた話
yukukotani
0
700
先を見据えたMVPのフロントエンド開発
yukukotani
0
290
Bundle Side Optimization in Future JavaScript - JSConf JP 2021
yukukotani
2
2.9k
Kotlin/JS の仕組み / How KotlinJS works
yukukotani
5
3.1k
Other Decks in Programming
See All in Programming
複雑な仕様に立ち向かうアーキテクチャ
myohei
0
130
デザインパターンで理解するLLMエージェントの作り方 / How to develop an LLM agent using agentic design patterns
rkaga
11
3.4k
Seamless Flutter Native Integration: FFI & Pigeon - Dreamwalker (JaichangPark / 박제창) @FlutterKaigi2024
itsmedreamwalker
0
120
Thoughts and experiences on Rust and TypeScript
unvalley
2
220
.NET 9アプリをCGIとして レンタルサーバーで動かす
mayuki
1
760
我々のデザインシステムは Chakra v3 にアップデートします
shunya078
2
2.9k
Arm移行タイムアタック
qnighy
0
410
5分ぐらいで分かる、トリミング機能の作り方
tsutsuitakumi
0
210
rails statsで大解剖 🔍 “B/43流” のRailsの育て方を歴史とともに振り返ります
shoheimitani
2
640
cmp.Or に感動した
otakakot
3
340
talk-with-local-llm-with-web-streams-api
kbaba1001
0
150
.NET Conf 2024の振り返り
tomokusaba
0
200
Featured
See All Featured
Code Review Best Practice
trishagee
64
17k
Producing Creativity
orderedlist
PRO
341
39k
Typedesign – Prime Four
hannesfritz
40
2.4k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
We Have a Design System, Now What?
morganepeng
51
7.3k
Unsuck your backbone
ammeep
669
57k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
29
2k
Testing 201, or: Great Expectations
jmmastey
40
7.1k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
What's in a price? How to price your products and services
michaelherold
243
12k
Transcript
僕が思い描く 勝手に TypeScriptの未来を 先取りする @yukukotani 2024/09/07 - Web Developer Conference
2024
自己紹介 小谷 優空 - @yukukotani ・VP of Technology @ Ubie,
Inc. ・Maintainer of KumaUI ・Student @ Univ. Tsukuba
今日の趣旨 Call-this operatorが好きすぎて僕だけ勝手に使っている話を延々とします 自由研究とか図画工作の類です
Call-this operator、なんなんじゃそりゃ Function.prototype.call の糖衣構文となる二項演算子 TC39で提案中のStage-1プロポーザル NEW!
Function.prototype.call、なんなんじゃそりゃ 任意の値をthisに束縛して関数を呼べる → Call-this operatorだと できる レシーバをthisに束縛
Function.prototype.call、なんなんじゃそりゃ 任意の値をthisに束縛して関数を呼べる → Call-this operatorだと できる レシーバをthisに束縛 そんなの使ったことないよ
いろいろな Function.prototype.call G プロトタイプ汚染の防6 G 組み込み関数のモンキーパッQ G メソッドの動的切り替! G etc...
いろいろな Function.prototype.call G プロトタイプ汚染の防6 G 組み込み関数のモンキーパッQ G メソッドの動的切り替! G etc...
僕らはそんなことしないよ
では僕たちアプリケーション開発者 にとって何がうれしいのか?
(1) classの代替
よくあるclassベースのモデル 抽象クラスUserには2種2 G RegisteredUser, AnonymousUser 両方からリソースのURLを取れる RegisteredUserだけはメールを送れる
TypeScriptのclassには色々なつらみがある classのメソッドはシリアライズ/デシリアライズできない(当然) Next.jsのServer Actionsのような境界で壊れがち user2.getUrl is not a function
TypeScriptのclassには色々なつらみがある TypeScriptの構造的部分型ではclassの名前が無視される 全く同じプロパティを持っていたら別クラスでも型が一致してしまう https://example.com/articles/foo UserにArticle代入できちゃう Userと全く同じシグネチャ idとgetUrl
TypeScriptのclassには色々なつらみがある classのメソッドにはDead Code Eliminationが効かず、バンドルサイズ肥大化 メソッドが依存する外部ライブラリ等のTree Shakeも芋ずる式に効かなくなる このメソッドは未使用なのに ビルド成果物に残ってしまう
TypeScriptのclassには色々なつらみがある そもそもclass一般の話題として、継承によるモデリングの限界も見えてきている https://speakerdeck.com/naoya/guan-shu-xing-puroguramingutoxing-sisutemunomentarumoderu?slide=54
人々はtypeと関数に救いを求めた G 振る舞いは純粋な関数として実8 G データはただのtypeとして定& G Tagged Unionで多態相当の表現
type+関数が結論なのか!? データはただのオブジェクトなのでシリアライズ・デシリアライズできる エラーにならない!
type+関数が結論なのか!? Tagged Unionのようにタグを付けておけば異なる型をちゃんと区別できる 発展的には Branded Type のようなテクニックもある エラー!kindが異なるので代入できない
type+関数が結論なのか!? Dead Code Elimination も当たり前に効く 未使用なので関数丸ごと消える
type+関数が結論なのか!? いいことづくしなのにclassを使い続ける人が多いのはなんでだろう
classのここが嬉しい! データに対する振る舞いが閉包的に定まる 普通に書けばデータそのものが振る舞いの名前空間となるから(prototype) userに対する振る舞いは getUrl, sendEmailに定まる
classのここが嬉しい! より直接的に言うと、レシーバを書いた時点でその振る舞いがわかる
type+関数だとメンタルモデルが異なる 関数ベースだと、まずグローバルな名前空間から振る舞いを探す必要がある (名前空間のためにオブジェクト作ったりするとTree Shakeできなくなる)
それ、Call-this operator でできるよ! レシーバにしたい型を This Parameter で定義 普通の引数の代わりに thisの型を定義
それ、Call-this operator でできるよ! 型が名前空間として機能し、 データ→型→振る舞い という紐付きで同定できる ~> を打ったタイミングで レシーバとThis Parameterを型検査
マッチするものだけ取り出せる
DEMO
(2) Tree Shake可能なユーティリティ
僕たちも嬉しい Call-this operator メソッドチェーンのDXとツリーシェイク可能なインポートの両立 zodとvalibotの良いとこ取りみたいなことができる 体験は良いけど Tree Shaking効かない 補完体験を維持しつつ Tree
Shakingも効く! Tree Shaking効くけど 補完体験が悪い
DEMO
よさそうなことはわかった 使いたい
Call-this operator、なんなんじゃそりゃ Function.prototype.call の糖衣構文となる二項演算子 TC39で提案中のStage-1プロポーザル NEW!
TC39? Stage 1? ECMAScriptの仕様を議論する委員会。仕様提案をStageに分けて管理している Stage 0 新しく提出されたプロポーザル。まだTC39の議論対象ではない Stage 1 Championと呼ばれる推進者が決まり詳細化されたプロポーザル。TC39の議論対象になる
Stage 2 セマンティクスや文法といった仕様の草案が定義され、その方向性に合意したプロポーザル Stage 2.7 仕様が決定し、原則承認されたプロポーザル。実装上の不都合がないかテストやプロトタイピングで検証する Stage 3 本番での実装が推 奨されるプロポーザル。実 世界で不都合がないか フィー ドバック を集める Stage 4 正式に承認されたプロポーザル。 ここか ら変更は 入らず、 次バー ジョンの EC MAScrip tに 含まれる
Babelプラグインで試したい Stage3以前の構文系の提案はBabelプラグインで試せるのが一般" D @babel/plugin-proposal-record-and-tuple (Stage 2 D @babel/plugin-proposal-throw-expressions (Stage 2)
@babel/plugin-proposal-throw-expressions
Babelプラグインじゃ足りなかった;; Babelはあくまでコードのトランスパイルだけやってくれる(当たり前) 今回は まで含めた開発体験を手触りしたい 補完や型検査
TypeScriptで試したい TypeScriptもまだブラウザで動かない新機能をサポートして ダウンレベルコンパイルしてくれる Explicit Resource Managementとか
TypeScriptにはまだ入らない;; TypeScriptはStage 3以降の提案のみを実装するポリシー Call-this operatorはまだStage 1 https://github.com/microsoft/TypeScript/blob/a709f989/src/lib/README.md
Stage 3に進めてもらい・・・たい・・・ https://github.com/tc39/proposal-call-this プロポーザルの最終コミットが1年前、tc39/agendas でも音沙汰なし
J.S. Choiさんが忙しそう Call-this operatorとかPipeline operatorのチャンピオン 本業は内科医なのにtc39とかUnicode Consortiumとかやってる謎の人 https://github.com/js-choi
標準化は待たずに 自由研究するしかない!
TypeScriptコンパイラを雰囲気で理解する https://github.com/microsoft/TypeScript-Compiler-Notes/tree/314256/intro 公式ガイドっぽいのがあったので斜め読み microsoft/Typescript-Compiler-Note
TypeScriptコンパイラを雰囲気で理解する https://github.com/microsoft/TypeScript-Compiler-Notes/tree/314256/intro 公式ガイドっぽいのがあったので斜め読み microsoft/Typescript-Compiler-Note
トークナイザの実装 入力したコードを意味のある単位で区切った配列にする 今回は新しいトークン `~>` が登場するので対応が必要 NEW!
トークナイザの実装 作戦:似たようなトークンを見つけて追いかける ./src/compiler/types.ts
トークナイザの実装 雰囲気でトークンを定義する ./src/compiler/types.ts ./src/compiler/scanner.ts
トークナイザの実装 すでにチルダをconsumeしてるところがあったので雰囲気で付け加える ./src/compiler/scanner.ts
トークナイザの実装 それっぽくトークナイズできた!
TypeScriptコンパイラを雰囲気で理解する https://github.com/microsoft/TypeScript-Compiler-Notes/tree/314256/intro 公式ガイドっぽいのがあったので斜め読み microsoft/Typescript-Compiler-Note
パーサの実装 トークン列を木構造(AST)に変換する
ASTを考える パーサーが吐くAST構造を考えるために、既存の似ている構文を観察する globalThis.window.closeまではPropertyAccessExpressionで それを呼び出すとCallExpressionで包まれる
ASTを考える Call-this expressionも同じ構造でいけるか? → `~>` があるなら () で呼び出さないと構文エラーなのでちょっと違う。
ASTを考える レシーバから呼び出し部分まで1つのノードに入れて、 PropertyAccessExpressionとCallExpressionの合いの子みたいにする receiver expression typeArguments arguments
パーサの実装 parser.ts から実装箇所を探したいが、1万行あるのでエスパーが必須 → 仮説: `expr.name` のピリオド解析時に PropertyAccessExpression を 作っているところに相乗りできないか?
パーサの実装 それっぽい関数があった。`expr.name` の `.name` の部分を解析していそう ここから親にたどってみる
パーサの実装 `expr.name?.foo.bar` みたいなチェーンを再帰的に解析している関数があった ここに相乗りできそう!
パーサの実装 `~>` があったら CallThisExpressionとして解析するようにして完了
TypeScriptコンパイラを雰囲気で理解する https://github.com/microsoft/TypeScript-Compiler-Notes/tree/314256/intro 公式ガイドっぽいのがあったので斜め読み microsoft/Typescript-Compiler-Note
エミッタの実装 ASTをJavaScriptとして出力する
エミッタの実装 CallThisExpressionノードの子ノードを順番に出力していくだけ
嬉しいですね 入力したTypeScriptを解釈してJavaScriptに出力するところまで一通り動いた!
嬉しくない Call-this parameterを解釈できるJavaScriptランタイムはたぶんない(それはそう)
トランスフォーマの実装 ./src/transformers 配下に target ごとの実装があり、 visitor pattern で変換している 今回は esnext.ts
に足していく
トランスフォーマの実装 `receiver.fn(arg)` を `fn.call(receiver, arg)` に変換。 既に色々なfactoryがあるので組み立てるだけ
嬉しいですね 一般的なランタイムで動くJavaScriptを出せた!
嬉しくない せっかくTypeScriptなのにぶっ壊せちゃう
型チェッカの実装 5万行のクソデカ型チェッカ checker.ts をどうにかする This parameterとレシーバの型の一致をチェックする以外は 普通の関数呼び出しと同じなのでパクって実装する 変更でかいので気になる人はコミット見てください(雑) https://github.com/microsoft/TypeScript/pull/58294/commits/ ce12997edd2302325e1463ec1554ae006d8ec3b3
嬉しいですね レシーバの型エラーが出るようになった
補完も効かせたい VSCodeのTypeScript ExtensionからTS Serverに補完依頼がくる VSCode TS Server `>` で補完だしたいのだが こちらのリストでございます!
補完も効かせたい まずExtension側で `>` でも補完を呼び出すようにする TypeScript Extensionは特別にVSCodeに組み込まれているので microsoft/vscode に手を入れる ./ extensions/typescript-language-features/src/languageFeatures/completions.ts
NEW!
補完も効かせたい TypeScript (TS Server) 側ではまず `>` が Call-this なのか確かめる じゃないと普通の比較演算とかでも補完がでて困っちゃう
補完も効かせたい 補完リストは以下のロジッR まずグローバルな関数呼び出しと同様のをリストアッ( その中からレシーバとThis Parameterが一致する関数に絞る
嬉しいですね 補完が効きます
DEMO
まとめ 5 Call-this operator が来るととても嬉しいで8 5 TypeScriptに変更を加えると新規機能が実装できて楽しいです
ありがとうございました