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
僕が思い描くTypeScriptの未来を勝手に先取りする
Search
Yuku Kotani
September 06, 2024
Programming
9
2.6k
僕が思い描く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
6.8k
Capacitor製のWebViewアプリからReact Native製のハイブリッドアプリへ
yukukotani
4
1.1k
Real World Type Puzzle and Code Generation
yukukotani
4
800
Kuma UI が提唱する Hybrid Approach CSS-in-JS の仕組み
yukukotani
2
460
GraphQLスキーマ設計の勘所
yukukotani
40
17k
既存Webサービスのモバイルアプリ版を 1週間でリリースし、進化させてきた話
yukukotani
0
650
先を見据えたMVPのフロントエンド開発
yukukotani
0
280
Bundle Side Optimization in Future JavaScript - JSConf JP 2021
yukukotani
2
2.9k
Kotlin/JS の仕組み / How KotlinJS works
yukukotani
5
3k
Other Decks in Programming
See All in Programming
ACES Meet におけるリリース作業改善の取り組み
fukucheee
0
120
Go製CLIツールGatling Commanderによる負荷試験実施の自動化
okmtz
3
650
AWS認定資格を受験するにあたり、気づいたこと・実践していたことのまとめ
satoshi256kbyte
1
120
pytest プラグインを開発して DRY に自動テストを書こう
inuatsu
2
240
Rails 8 Frontend: 10 commandments & 7 deadly sins in 2025
yshmarov
1
590
"noncopyable types" の使いどころについて考えてみた
andpad
0
130
タイミーにおけるデータの利用シーンと データ基盤の挑戦
marufeuille
4
3.1k
What is TDD?
urakawa_jinsei
1
200
フロントエンドの標準仕様をどう追っているか / How I follow the frontend standards specs
petamoriken
2
170
App Router 悲喜交々
quramy
7
370
型付きで行うVSCode拡張機能開発 / VSCode Meetup #31
mazrean
0
220
推しの夫に恋のGPS「ときメーター」#M5Stack #IoT #M5JPTour2024
riyu
0
220
Featured
See All Featured
Design by the Numbers
sachag
278
19k
The Language of Interfaces
destraynor
154
24k
VelocityConf: Rendering Performance Case Studies
addyosmani
324
23k
Thoughts on Productivity
jonyablonski
67
4.2k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
246
1.3M
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
How To Stay Up To Date on Web Technology
chriscoyier
786
250k
Automating Front-end Workflow
addyosmani
1365
200k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
504
140k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
28
7.5k
Building Adaptive Systems
keathley
37
2.1k
Making Projects Easy
brettharned
114
5.8k
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に変更を加えると新規機能が実装できて楽しいです
ありがとうございました