3月19日、海外のテクノロジーメディアThe New Stackが「Microsoft TypeScript Devs Explain Why They Chose Go Over Rust, C#」と題した記事を公開した。この記事では、TypeScriptコンパイラをGoへ移植した背景や、その理由について詳しく紹介されている。
以下に、その内容を紹介する。
先ごろMicrosoftは、TypeScriptのコンパイラを新たなプログラミング言語であるGoに
移植することを発表した。多くの開発者が注目する中、 「なぜMicrosoft独自のC#や、今話題のRustではなくGoなのか」という疑問も多く寄せられたようだ。
TypeScriptの開発チームは、GitHubやReddit、YouTube、
Hacker Newsなどで情報を積極的に共有し、Goを選択した理由や、コンパイラ移植の狙いについて解説している。
なぜC#ではなかったのか
TypeScriptの現在のコンパイラはTypeScript自身で書かれている。Redditで、あるユーザが「C#にはTypeScriptの再実装に必要なほとんどの機能があるのではないか」と指摘したところ、「そのC#とTypeScriptを作った本人(Anders Hejlsberg)がGoを選んでいる」というユニークな返答があったという。
実際にAnders Hejlsberg(C#やTypeScriptの設計者)は、移行を発表する動画などで「 なぜC#ではないのか 」という問いに答えている。
その理由はC#が“バイトコードベース”であり、すべてのプラットフォームにわたるネイティブコードの最適化サポートに制限があること、そしてオブジェクト指向(OOP)に最適化された言語である点を指摘したうえで、TypeScriptの既存コンパイラの構造は「関数とデータ構造主体」であり、C#へそのまま移植するとパラダイムの違いから大きな摩擦を生む可能性があると述べている。
Hejlsbergによれば、 Goは「最適化されたネイティブコードをあらゆるプラットフォームで扱える」「データレイアウトを詳細に制御できる」「ガーベジコレクションを備え、並行処理にも強い」などの特性を持ち、 TypeScriptコンパイラのニーズに適していたという。C#は.NETのAOT(Ahead-of-Time)コンパイルがすべてのプラットフォームで利用できるわけではなく、またRustやC++のような“低レベル”の最適化にも及ばない点が挙げられている。
一方でC#は.NETとともにMicrosoft内部で最も多く利用されている言語であることに変わりはないようだが、今回に限ってはTypeScriptの現行コードベースをそのまま移植するうえで、Goが最適だったという結論に至ったようだ。
なぜRustではないのか
TypeScript開発リードのRyan Cavanaughも、
Reddit上で Rustを選ばなかった理由 を明かしている。Rustは優れたパフォーマンスと安全性を備えているが、TypeScriptの現行コードの移植に際しては「ガベージコレクション前提のデータ構造」を無理にRust向けに書き換える必要があり、大規模な変更や“unsafe”コードの導入が避けられないという。
同氏によれば、以下のような選択肢があったとされている。
- Rustでゼロからコンパイラを再設計し書き直す(数年かかる可能性があり、既存のTypeScriptと互換性のない仕様になるリスクがある)
- Goを使って既存コードをほぼそのままポートし、およそ1年で実用的な成果を得る
さらにCavanaughは、プロジェクトのFAQで次の2点を結論として挙げている。
- 「ゼロから作り直す」のであれば、他の多くの言語も十分に選択肢に入る
- しかし既存のコード資産や要件を踏まえた場合、Goが最もバランスよく適合した
また、Goによるコンパイラ実装はswcやoxc、esbuildなどの既存ネイティブTSパーサを検討したうえでの判断でもあるという。Rustにおける最大のメリットであるメモリ管理に関しても、コンパイラでは「最終的なチェックが完了するまでは基本的にメモリを解放できない」ため、GoのGCモデルのほうが実運用に合致しているようだ。
同様に、SWCプロジェクトの開発者であるDongYoon Kang氏がTypeScriptの型チェッカーtscを書き直す際にも、RustではなくGoを選択していたことを指摘する声もあった。Cavanaughはこれを「kdy1(SWC開発者)は正しいアプローチを示した」と評価している。
メリットとデメリット
Zoomでのインタビューによれば、Hejlsbergは「Goの型システムはTypeScriptほど豊富ではないが、一方でビット操作やメモリ配置の細かな制御が可能で、その結果、メモリ使用量は旧コンパイラの半分ほどになった」と述べている。また、JavaScriptとは違い、Goではバイトや短整数、64ビット整数などを明示的に扱えるため、TypeScriptコンパイラのようなシステムレベルのプログラムには適しているという。
従来、JavaScriptは「計算集約的なシステムレベルの処理には向いていない」とされてきたが、TypeScriptはJavaScript上でコンパイラを動かしていた。Hejlsbergは「Goはシステムレベルを意識した言語であり、TypeScriptコンパイラはまさしくシステムレベルのプログラムだ」と説明している。
GitHub上のディスカッションでも、Microsoft内部ではC#やGo、Java、Rust、C++、TypeScriptなど複数の言語を状況に応じて使い分けていると強調されている。C#が社内で最も人気のある言語であることも事実だが、あくまで「最適な場面で最適な言語を使う」という方針のもと、今回のTypeScriptコンパイラの移植にはGoが適していたという結論に至ったようだ。
もちろんC#や.NETが依然として多くのプロジェクトで強みを発揮している点も繰り返し語られている。しかしながら今回のポートは、 既存のコードベース(クラスを多用しない構造)を保ったまま移行することが主眼 であり、その点でGoの構造がより「1対1対応」に近い形で移しやすかったという。Microsoft内部での方針は多言語共存であり、「以前なら考えられなかったかもしれないが、今のMicrosoftは最良のツールを選択することを優先する」という姿勢が強調されている。
結果としてGoの採用は「 10倍のパフォーマンス向上 」をもたらすとのことで、Microsoftが選んだアプローチがどのような成果を生むのか、多くの開発者が注視している状況だ。
詳細はMicrosoft TypeScript Devs Explain Why They Chose Go Over Rust, C# を参照していただきたい。