Cloudflare と VoidZero、TypeScript コンパイラを Rust に移植
tsrs は 4 つの実プロジェクトで TypeScript 7.0 より 3.8〜8.1 倍速く、ピークメモリは 2 割ほど。フォークせず、TypeScript チームの判断に追従しながら Vinext と同じエージェント運用で上流と同期する。
日本語
コピー

Cloudflare と VoidZero は、Owner.com の Max Schwenk と協力して tsrs を開発している。TypeScript コンパイラを Rust に移植したものだ。この作業は TypeScript チームと密に連携しながら進めており、tsrs は Oxc JavaScript コンパイラツールチェーン の一部としてインキュベートしている。
狙いは、開発者がコードチェックの待ち時間を減らし、コードを書く時間を増やすことにある。TypeScript が速くなり、メモリ消費も少なくなれば、完全な開発環境をより多くの場所に届けられる。ブラウザに直接持ち込むことも可能になる。
念のため言っておくと、私たちは TypeScript をフォークしていない。この言語の設計と方向性は TypeScript チームが完全に握るべきだと考えている。同チームは長期的なビジョンを持ち続けながら、TypeScript を JavaScript コミュニティ全体に広めてきた。そこを変えるつもりはない。
TypeScript チームは多くの点でかなり速く動く一方、一部の機能については何年もかけて意図的に複数の案を探り、プロトタイプを作り、しかる後に正しい実装を選ぶことがある。Rust 移植はその決定に追随しなければ、やがて崩れ、互換性を失う。TypeScript 言語を変えないために、私たちは元の実装を厳密に基準としなければならない。そして、あるべき姿を決めるのは TypeScript チームだけであるべきだ。
パフォーマンスとメモリの改善
Rust 版 TypeScript 移植の初期ベンチマーク結果は楽観的だ。型チェックの worker 数が同じ条件で、tsrs は TypeScript 7.0 より最大 8 倍速く、メモリ使用量は約 70% 少ない:

ご覧のとおり、TypeScript の次のバージョンはすでに多くの性能改善をもたらしており、TypeScript 7.1 beta は TypeScript 7.0 より最大 2.5 倍速い。最適化の一部は tsrs からアップストリームでマージされたもので、さらに多くを見つけたいと考えている。
最近の各種 TypeScript 移植版のベンチマークを見た人もいるだろう。さまざまな性能データが示されているが、これは多くの場合、TypeScript のデフォルト設定と比べて大規模なマシン構成や異なるオプションを使っているためだ。私たちは TypeScript チームと協力し、上記のベンチマークが同じ構成を比較していることを確認した。
デフォルトでは、tsrs はマシン構成に合わせて自動調整する設定を備えている。メモリを多く使うが、その分速い:

tsrs を試す
TypeScript in Rust の目標は、TypeScript を忠実に移植することにある。npm から tsrs パッケージをインストールすれば、実験版を試せる:
npm install tsrs
npx tsrs
なぜ今なのか
ここ数年、TypeScript を他の言語へ移植する試みは少なくなかった。だが、あまりに複雑なため、成功したのは一度だけだ。TypeScript チームが TypeScript を JavaScript から Go へ移植したときである。
しかし今では、最先端の AI モデルが大規模な移植をほぼ単独で、しかも数日でやり遂げてしまう。slopforks、忠実な移植、Rust や C++ でアーキテクチャを一から設計し直した TypeScript 版まで、すでに登場している。より速い TypeScript が求められているのは明らかだ。
なぜ Rust なのか
「TypeScript の Go 移植版は、以前の TypeScript 版より 10 倍速く、メモリ効率もはるかに良い。それでは足りないのか」と思うかもしれない。
だが、話は速度だけではない。Rust には独特の強みがある。WebAssembly で動かせることだ。Rust + Wasm が昔から強力な組み合わせであり続けてきた理由の一つは、Rust という言語設計が持つ低レイヤーの性質にある。Go のプログラムを Wasm にコンパイルするときは、Go のガベージコレクタも一緒にコンパイルしなければならない。Rust のメモリ管理モデルなら、WebAssembly guest と host の間のメモリのやり取りが素直になる。メモリ効率こそ、Rust が WebAssembly の場面に向く決定的な理由の一つだ。
Cloudflare Workers は以前から Wasm をサポートしてきた。ほんの数週間前には、wasm-bindgen に追加された Emscripten target によってWorkers で Rust をネイティブにサポートすると発表した。ソフトウェアのビルドとデプロイのシステム一式を Workers 上でタイトなループで回せば、メモリフットプリントの小ささが効いてくるのはすぐに分かる。つまり、こうしたワークロードを十分に効率よく動かせるようになり、これまで完全なクローズドな開発システムを動かせなかった環境でも動かせるようになる。
そこに agent が加わると、新しい可能性が開ける。Cloudflare 上の完全にサンドボックス化された環境で、開発ツールチェーンを端から端まで動かせるのだ。Wasm があれば、ブラウザのクライアント、組み込み機器、IoT アプリケーションの中でも、そうした環境を安全に動かせる。
tsrs の移植版はどう保守するのか
まず、Theo Browne と協力して tsc-rs と tsrs を一つのパッケージに統合し、Language Server Protocol(LSP)や content mapper を含む TypeScript の全機能をサポートする。次に、Vinext を上流の Next.js と同期させ続ける取り組みで、すでにかなりの実績を積んでいる。具体的な方法は最近のブログ記事に書いた:
毎朝、agent が変更をレビューし、diff を取得し、Vinext に影響しうる問題があれば追跡 issue を立てる。毎晩、互換性マトリクスを再生成し、Next.js のテストスイートで Vinext を走らせる。テストや issue がギャップを露呈すれば、agent は両方のコードベースで対応する変更を特定し、再現を作り、関連するテストを移植し、修正をコミットできる。
同じ流れを TypeScript にも適用する。ただし、上流の TypeScript の挙動と食い違う箇所を持ち込まないよう、細心の注意を払う。性能改善が見つかれば、TypeScript Go のコードベースに還元し、みんなが恩恵を受けられるようにしたい。
現時点で上流の TypeScript との間には、診断メッセージの出力順など、いくつか差異が残っている。安定版を出す前に、こうした差異を最小限に抑えるのが目標だ。
次のステップ
Cloudflare には、JavaScript エコシステムを支える無料のオープンソース Rust ツールがすでに数多く集まっている。Vite、Rolldown、Oxlint、Oxfmt などだ。1000 万人を超える開発者が Cloudflare 上でアプリを構築しており、その土台となる開発ツールチェーンをより速く、より移植しやすく、より多くの環境で動かせるようにすることに大きな関心を寄せている。tsrs を私たちのスタックにもっと深く統合していく実験、たとえば Oxlint の型を考慮した lint ルールなどに、大きな期待をしている。
Vinext と同じく、tsrs を、TypeScript 本体の妨げにならない、よく保守された健全なオープンソースプロジェクトにするのが目標だ。Oxc チームはすでにコードベースのリファクタリングに着手しており、より速く、メモリ使用量が少なく、保守しやすい形にしようとしている。TypeScript チームもこれを重視していることは承知している。彼らは tsc のメモリと性能の改善を実験しているところだ。TypeScript チーム、そして JavaScript コミュニティと協力し、最良で最速の TypeScript 実装を一緒に作っていきたい。