🍣

TSKaigi 2025「TypeScriptとは何であって何でなく、誰のもので、どこへ向かうのか」スピーカーノート

に公開

導入

今日は「TypeScriptとは何であって何でなく、誰のもので、どこへ向かうのか」というタイトルでお話させていただきます。よろしくお願いします。

まず最初に、軽く自己紹介をさせていただきます。Suzuki Sosuke と申します。ユビー株式会社でソフトウェアエンジニアをしています。今日ブースやってるので遊びにきてください。あと趣味でPrettierというコードフォーマッターのメンテナンスをしたり、WebKitのReviewerをやっていたりします。WebKitといってもJavaScriptCoreの部分だけなんですけどね。

で、トークの方に移っていくんですが、今回のトークのタイトル、まるで基調講演のような壮大なタイトルだなと思われるでしょう。自分でもめちゃくちゃそう思うんですが、こうなってしまったのには一応ちゃんと理由があります。というのも、今のTypeScriptのエコシステムは激しく変化している最中で、色々な大きな変化がドカドカとやってきています。たとえば、目立つもので言えば Node.js による type stripping とか、TypeScript の Go 実装とか、色々ありますよね。そういう一つずつの要素について具体的に解説することには、それはそれで大きな意味があります。一方で、TSKaigiという、TypeScriptについて考えられる人がおそらく日本で一番集まる場所においては、少なくとも僕はその激しい変化の裏側にあるモチベーションだとか、そこから予想される今後の変化の方向性みたいな、抽象的な話をしたいと思ってしまいました。で、がーっとトークのプロポーザルの概要を書いて、タイトルを一生懸命考えたんですが、なかなか良いのが思いつかなくて、頑張ったんですがめちゃくちゃ壮大なタイトルになっちゃった、というわけです。

まああとやっぱり、個人的なスタンスとして、来週からの仕事の役に立つような話はカンファレンスではしたくないんですよね。僕は一応今日ユビーのブースにも立たせていただいていますが、基本的にはパソコンとJavaScriptとTypeScriptのファンとして来ていて、仕事のファンではないので、まあ30分くらいそういう話をお聞きいただいて、そのあとブースに立ってたりそのへん歩いている自分を捕まえて議論をふっかけたりしてください。当然僕抜きで議論したって良いと思いますし。

とにかく、みなさんがJavaScriptとかTypeScriptとかについて、来週からの仕事には特に役にたたないことについて考えるきっかけになれば嬉しいかなと思います。

TypeScriptってどんな言語?何が変?

では、ここから本題に入っていきます。

僕は、TypeScriptのことがめっちゃ大好きで仕方がないんですが、このTypeScriptってやつは実はかなり変なプログラミング言語なんですよね。

まずはみなさんご存知だとは思いますが、TypeScriptという言語は基本的にはJavaScriptにコンパイルされてから実行されます。世の中にはJavaScriptにコンパイルされる言語というのはたくさんあります。そういう言語とか処理系のことを、もう今となってはあんまりこの言葉は聞きませんけども、AltJSとか言いますね。AltJSとして有名なものとしては、MetaのFlowとか、PureScriptとか、Elmとか、CoffeeScriptとかがありますね。あとは他の用途でも使われるプログラミング言語がJavaScriptへのコンパイルもサポートしているという例で言えばKotlinやScalaなんかもAltJSの一つだと見ることができますね。TypeScriptも、そういったAltJSの一つというわけです。そして、TypeScriptはこのAltJSの中でも少し特殊なやつと言えます。MetaのFlowもそうですが、シンタックスがJavaScriptのものに型のためのものを加えたまあ厳密にはちょっと違うんですがスーパーセットになっていて、いわば型の構文ありのJavaScript、という感じになっているということです。要は、JSにない言語機能とかは基本的にはないわけです。ヒント情報を伝えるための構文を持つかなり賢いリンターくらいに思っていたほうが実態に近いかもしれません。このような性質を持つ言語だからこそ、JavaScriptとの相互運用性を高く保つことができ、JavaScriptプログラマーが簡単に使い始めることができ、結果としてここまでの人気を得たのでしょう。まあ、だからこそ例外的であるenumとかが嫌われていたりするのかもしれませんね。個人的にはそんなに嫌いではないですが。

この、AltJSという、コンパイルターゲットがかなり高レベルな言語であるという性質によって、ビルドレイヤとランタイムレイヤが良くも悪くもソフトウェア的には疎結合で、ややエコシステム全体を見渡してみるとややいびつであるような状況が生まれています。ビルドレイヤとランタイムレイヤの間での決まり事としては「普通のJavaScriptになっていてくれ」ということだけですので、ランタイムとか処理系からすればTypeScriptのことは特に気にする必要はないわけです。さらに、入力として渡ってくるものがJavaScriptの形をしてさえいれば、どんなソフトウェアによって生成されたコードであっても良いんですよね。なので、Microsoftが開発している公式のTypeScriptコンパイラではないTypeScriptのコンパイラというのが世の中にはたくさんあり、どれもそれなりに使われています。たとえば、昔からあるものだとBabel、ここ5年くらいで登場してきたものだとSWCやesbuild、oxcなどがあります。ホビーユースのものも含めればもっとたくさんありますね。なんでこういうことが起こっているかというと、Babelの場合はちょっと違いますが、MicrosoftのTypeScriptコンパイラの実行速度が遅いからです。そのため、傾向としてそういうTypeScriptのコンパイラの代替はRustやGoといった速いプログラムを書きやすいプログラミング言語で記述されることが多いです。

一方でですね、大きな問題として、TypeScriptの本質であり、最も重要な価値の部分である型チェッカーに関しては、Microsoft公式のTypeScriptコンパイラのみが唯一の実装であるような状況がずっと続いています。ezcoやstcといった、TypeScriptの型チェッカをRustやGoで書き直そうとする野心的なプロジェクトはいくつかありましたが、どれもプロダクションで使える完成度には至っていません。なんでそんな状況になってしまっているかというと、型チェッカーの実装がデカく難しく仕様がないからであると思います。TypeScriptコンパイラの型チェッカーの部分はおもにchecker.tsというファイルに記述されていて、コイツがとても大きいことは一部業界では有名ですが、昨日のお昼の時点でなんと1ファイル2.97MB。なんとGitHubのビューワーではコードを見ることができませんでした。アクティブに変更され続ける checker.ts の動作を、別言語に正確に移植し、さらにそれを継続してメンテナンスすることがどれほど難しいかは想像に難くないでしょう。

こういう状況があると、TypeScriptのプログラマーとしてはなんだかすごく微妙な使い勝手になってしまうわけですね。トランスパイルの部分は速くしたいから非公式のTypeScriptコンパイラを使っていて、しかし型チェックの部分はMicrosoft公式のTypeScriptコンパイラを使わなければならない、という状況です。ツールの性質を理解してちゃんと設定するのってプロダクト開発からしたらまあまあ不毛だと自分は感じてしまいます。さらに型チェックまでちゃんと実行したいときの実行速度は公式のTypeScriptコンパイラの実行速度の方に引っ張られるので、嬉しさも半減、みたいな。そういう速いツールがないよりは本当に全然良いんだけど、まだまだ結構めんどくさくて困っちゃう。こういうTypeScriptのエコシステム、特にコンパイラに関するツールチェインにまつわる諸問題は、言語やコミュニティの過渡期だったために必然的に生まれてしまったものだとは思っていますが、やはりユーザーとしてはめんどいです。

2010年代後半以降のTypeScriptエコシステムはどう変化してきた?

ここまでTypeScriptの悪口を言ってしまったので、ここからは褒めていきましょう。

2010年代後半から、TypeScriptのツールチェイン周辺のエコシステムは少しずつ変わってきたように感じます。ここには、大きく2つの流れがあるかなと思っています。1つめは、TypeScriptファーストな世界観、2つめはツールチェインの高速化です。

まず1つめの、TypeScriptファーストな世界観について考えてみます。フロントエンドもバックエンドも主流なフレームワーク、ライブラリのほとんどはTypeScriptを第一級にサポートしている、というかそれ自体がTypeScriptで書かれています。Next.jsなんかは普通にセットアップすればTypeScriptになりますよね。使いたいライブラリがJavaScriptで記述されているという理由でDefinitelyTypedに型定義を探しにいったり、存在しないからDefinitelyTypedに型定義を追加したりといった作業をする回数は、昔と比べて格段に減りました。さらに2018年にライアンダールが発表したDenoはTypeScriptの実行をサポートしています。さらに後続のJSランタイムの一つであるBunも同じようにTypeScriptをサポートしています。これらのランタイムでは、TypeScriptのビルドレイヤというものの存在を全く気にすることなくコーディングすることができるのです。最近ではNode.jsも型のストリップ、ようはTypeScriptの直接の実行をサポートするようになりました。今すぐにこれをプロダクションで使おうという人は少ないかもしれませんが、これはNode.jsの方向性を予想する上で重要な新機能だったといえるんじゃないでしょうか。

さらに、JavaScriptの標準化の方面でもそういう話が出てきています。JavaScriptの標準化委員会であるTC39にはType Annotationsというプロポーザルが提案されています。これはJavaScriptの仕様にTypeScriptのような型の構文を追加するものですが、この型の部分はJavaScriptにとってはコメントのようなものとして扱われます。ブラウザ上のJSエンジンが型チェックを行うわけではなく、単に型ヒントをJS上に書けるようになり、それをどこかで型チェックした上でそのまま実行できる、というプロポーザルです。これはとてもおもしろい提案だと思っていて、個人的にはとても期待をしていたんですが、やはり難しいみたいで最近は進捗が全然ないようです。残念ですね...。もしこれがきたらめちゃくちゃTypeScriptファーストではあると思います。

さて次は、TypeScriptのエコシステムの変化の大きな流れの2つ目である、速さをウリにしたツールチェインについて考えてみましょう。さっきもちょっと名前を出しましたね。最初に有名になったのはなんだったでしょうか。自分の記憶が正しければSWCとかだったような気がしますが...ちょっと定かではありません。SWCは、みなさんご存知とは思いますが、JavaScriptのトランスコンパイラです。それまで主流だったBabelが遅かったから、韓国の大学生だったDonnyが開発しました。その後DonnyはVercel社に雇用され、SWCはNext.jsのデフォルトのトランスパイラになり、SWCの開発を続けています。他にもVercelはwebpackの作者であるSokraを雇用してwebpackの後継を名乗る高速なバンドラーであるTurbopackの開発に力を入れるなどして、ツールチェインの高速化に取り組んでいます。さらに、元Figma CTOのEvanによるesbuildの登場も衝撃的でした。esbuildはGoで書かれたバンドラーで、webpackというよりかはRollupに近い比較的シンプルなバンドラーなのですが、他のバンドラーと比べてあまりにも速かったため、自分も当時大きな衝撃を受けたことを覚えてますね。あるときからPrettierのビルドに使うバンドラーをRollupからesbuildに切り替えたんですが、普通に10倍とかそういうレベルで速くなってめっちゃ開発が楽になって超嬉しかったです。esbuildはバンドラーですが、トランスパイルの機能を自分で持っていてトランスパイラとして使うこともできます。さらに最近ではoxcというこれまためっちゃ速いRust製のJavaScriptツールチェインが開発されています。oxcはBoshenというエンジニアが作ったソフトウェアです。彼はEvan Youが昨年立ち上げた会社Void(0)にジョインし、仕事としてoxcの開発を行っているようです。さらには、TikTokで有名なBytedance社もRspackなどを開発しています。Rspackは、webpackとの互換性を重視していて、基本的なプラグインやローダがそのまま動作します。最近、Next.jsから試験的に使えるようになったことで少し話題になりましたね。個人的には、ユースケースが発明されたあとのソフトウェアとはいえ、かなり作るのが大変であろうものを作り上げてしまう人がこんなにいるということに正直に言って驚いています。

今ここであげたツールはいずれも、さきほど言ったようにTypeScriptのコンパイルを担うだけのもので、TypeScriptの本質である型チェックの仕事をするソフトウェアではありません。しかし、なんと、この3月にアンダース・ヘルスバーグ先生が「A 10x Faster TypeScript」というブログを公開しました。これはめちゃくちゃアツい記事で、雑に要約すると「TypeScriptで書かれた現在のTypeScriptコンパイラをそのままGoの実装に移植し、並列化などの最適化も合わせて、なんと10倍以上の高速化を実現した」ということらしいんですよね。つまり、みんなが待ち望んだ型チェックの高速化、ということです。これまで何人かの人が挑んでは敗れてきた、型チェッカーをより高速な言語で書き直すという取り組みに、マイクロソフト自らが取り組むということで、これは期待が高まりますね。今、TypeScriptは5.x系ですが、7.x系からこのGoの実装をメインにすることを計画しているようです。ちなみに、新しいJSツールチェイン系はRustで書かれていることが多い中Goを選定したのは、TypeScriptで書かれているコードをデータ構造やアルゴリズムをまるっと移植するにあたってGoの方が都合が良かったかららしいです。まあそれはそうかもしれないですね、と個人的には思っています。他に、個人的な気になることとしては、このGo版のTypeScriptコンパイラがちゃんと完成して、十分に速かったらoxcとかswcみたいな高速なトランスパイラはどうするんだろう?ってところですかね。少なくともoxcやswcが生まれたモチベーションというのは、BabelやTypeScriptコンパラが遅かったからなはずで、そのモチベーションがなくなってしまったらどうするんだろう?っていうのは素直に気になりますよね。まあでも、彼らのツールチェインの中でシームレスに使えるコンポーネントとして残すのかもしれませんね。バンドラと統合するとかそういうことを考えると自分たちで持っていたほうが便利そうな気もします。ちなみに、このTypeScriptコンパイラ自体の実装をGo言語に移植する話についての詳細は明日berlysiaさんがしてくれるので楽しみに待ちましょう。

そして、これらの取り組みの多くが、個人の趣味ではなく企業の活動として行われているということも重要です。BabelやPrettier、ESLintなどのこれまでも使われてきたJavaScript系のツールはボランティアのメンテナーと寄付金によって賄われてきました。これは全然持続可能ではなく、狂人の謎のモチベーションによって維持されています。僕もそういうの趣味でやっていますが、本当に謎だなと、自分でも思います。そういう謎めいたモチベーションではなく、明確なビジネス上のリターンを見込んで会社がやっているのであれば、その会社の方向性やビジネスに気を払わなければいけないという別の欠点も出てきますが、これまでのOSSに対してしていたような持続性に対する心配はしなくてよくなります。しかも、これらの企業間に競争が生まれそうなのですごく良いなと思っています。競争があるとソフトウェアは大体速くなるので!

さらに、今後のTypeScriptエコシステムのさらなる変化を予測する

さて、これまで具体的なTypeScriptとそのエコシステムの進化について見てきました。ここから、今後どうなっていくのかを少し考えてみましょう。

個人的には、「TypeScriptをコンパイルしてJavaScriptに変換してから実行する」というビルドレイヤの存在が、どんどん溶けてより透明になっていくのだと思います。ようは、誰にも意識されずにずっとそこにあるような状況に、どんどんなっていくのだと思います。

コンパイル速度が超速くて、それがランタイムやエディタと統合されていたら、普通のプログラマーはもはやその存在を意識する必要はないし、存在しないも同然です。そして、多分そのようになっていくでしょう。

しかし、ここで注意しなければならないと思っているのは、フロントエンドとバックエンドでは全然事情が違うだろうということです。ここ数年、TypeScriptはフロントエンドでもバックエンドでもよく使われるプログラミング言語の一つとなりました。フロントエンドではJavaScriptはWebブラウザで相変わらず元気に動いていますし、バックエンド用途では、昔からあるNode.jsも当然そうだし、DenoやBunといったランタイムの選択肢も増えてきました。

そして、バックエンドにおいては割とすぐTypeScriptのビルドレイヤというのは全く意識されなくなると思います。DenoやBunにおいてはすでにそうだと思いますが、Node.jsにおいてもそうなると思います。これはランタイムを支配できるのがサービス提供者だからです。Node.jsがTypeScriptをサポートするようになった今、ノウハウなどが一般に知れ渡ればそういう、明示的なTypeScriptのビルドをしないアプローチを取るサービスも全然出てくるでしょう。

が、一方でフロントエンドの方はそうはいかないでしょう。フロントエンドにおけるランタイムはWebブラウザであり、それを支配するのはサービス提供者ではなくユーザーです。どのブラウザのどのバージョンを使うかを決めるのはサービス提供者じゃなくてユーザーです。しかも、そのランタイムで動くのは僕らのサービスだけじゃなくて、これまでWWWに公開されたすべてのJavaScriptプログラムなわけです。そういうプログラムがちゃんと高速に動き続けられるType Annotationを策定して実装するのは、、、まだまだ遠い未来になりそうです。さらに、もし、もしもType AnnotationがきてTypeScriptのビルドレイヤを消せるようになったとして、フロントエンドエンジニアの皆さんは本当にそのビルドレイヤを消すのでしょうか?僕はそうはならないだろうと思っています。どうせ、僕たちはバンドルやミニファイをしたいので、そのためのビルドステップを消さないわけで、そしたら型のストリップも一緒にしちゃいますよね、ふつう。実は僕は書いたJavaScriptが直接ブラウザで動く未来が来ることをずっと夢見ているのですが、まだまだその夢は遠そうです。結局、今と同じようにNext.js/Nuxt.jsのようなメタフレームワークのレイヤで上手く吸収されることになるのでしょうねえ。なんだかちょっと残念な感じだなと思います。

結論としては、フロントエンドの方は、今と同じような開発体験、しかしめっちゃ速い!みたいな感じになるんじゃないかと予想しています。でもそれってそんなに悪くないかもしれませんね。そして、バックエンドもフロントエンドも、ありきたりな話ですが、技術に対する審美眼を磨いて、主流に乗り続けるというのが快適な開発体験を得るためには重要だと思います。もちろん、自分たちの要件に照らし合わせて考えるというのは大前提として。いずれにしても、ランタイムやフレームワークなど、何かのブラックボックスに乗っかる形でTypeScriptを使った開発体験が設計されていくことは、少なくともここ数年は間違いないと思っています。乗るべきブラックボックスを間違えないことが大事だと思います。

そのためには、技術そのものの性質は当然のこと以外やや開発元を含めたパワーバランス、そして技術の変化に目を光らせておくことあるいは、ブラックボックスの中身を見透かす力を持っておくことが重要そうだと思います。今日あげたような流れをおさえた上で関連技術をウォッチしておくと、いろんなモチベーションや経緯がわかって、そのための一助になるんじゃないかと思います。

まとめ

  • TypeScriptは、いわゆる普通のプログラミング言語じゃない
    • コンパイルターゲットがめっちゃ高級言語のJavaScriptである
    • 「TypeScript」それそのものは、JavaScript本来の構文に加え、ヒントとしての型情報を解釈できる「賢いリンター」
  • TypeScriptのエコシステムはOSSによって作られ、ニーズが示され、ユースケースが確立されてきたが、それでもやっぱり本質的な部分ではMicrosoftの影響力がとてもとても大きい
    • TypeScriptは、エコシステムの中で溶けていき、我々普通のプログラマーはその実態をあんまり意識しなくなるだろう
  • DefinitelyTypedをせこせこ書いていたときと比べたら今もだいぶ意識していないよね
  • しかし残念ながらフロントエンドではそうはいかない
  • とはいえ、めっちゃ速く、良い体験になっていくだろう。実はそれってめっちゃ嬉しい

Discussion