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
10
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.2k
Real World Type Puzzle and Code Generation
yukukotani
4
810
Kuma UI が提唱する Hybrid Approach CSS-in-JS の仕組み
yukukotani
2
470
GraphQLスキーマ設計の勘所
yukukotani
40
17k
既存Webサービスのモバイルアプリ版を 1週間でリリースし、進化させてきた話
yukukotani
0
660
先を見据えた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
学生の時に開催したPerl入学式をきっかけにエンジニアが組織に馴染むために勉強会を主催や仲間と参加して職能間の境界を越えていく
ohmori_yusuke
1
140
Real-time message handling and notifications with API Platform and Symfony
alli83
1
110
CSC509 Lecture 04
javiergs
PRO
0
150
A Journey of Contribution and Collaboration in Open Source
ivargrimstad
0
610
モジュラモノリス、その前に / Modular monolith, before that
euglena1215
6
710
クラウドサービスの 利用コストを削減する技術 - 円安の真南風を感じて -
pyama86
3
400
MLOps in Mercari Group’s Trust and Safety ML Team
cjhj
1
120
How to debug Xdebug... or any other weird bug in PHP
dunglas
2
1k
Quarto Clean Theme
nicetak
0
220
(Deep|Web) Link support with expo-router
mrtry
0
180
2024-10-02 dev2next - Application Observability like you've never heard before
jonatan_ivanov
0
180
ROS 2のZenoh対応とZenohのROS 2対応
takasehideki
2
310
Featured
See All Featured
Understanding Cognitive Biases in Performance Measurement
bluesmoon
26
1.4k
[RailsConf 2023] Rails as a piece of cake
palkan
49
4.7k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
4 Signs Your Business is Dying
shpigford
180
21k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
92
16k
Designing for Performance
lara
604
68k
Music & Morning Musume
bryan
46
6.1k
Typedesign – Prime Four
hannesfritz
39
2.3k
Side Projects
sachag
452
42k
From Idea to $5000 a Month in 5 Months
shpigford
381
46k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
130k
Bash Introduction
62gerente
608
210k
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に変更を加えると新規機能が実装できて楽しいです
ありがとうございました