メインコンテンツまでスキップ

TypeScriptは何ではないか?

多くの開発者がTypeScriptを高く評価しています。そのような中、誤解の上にTypeScriptを過度に高評価する人もいます。TypeScriptも魔法の杖ではありません。本稿では、TypeScriptが何を解決してくれないのかを見ていきます。TypeScriptでできないことを無理にやらせようとしても、その努力は無駄になりますから、これを理解することは重要です。

実行時の高速化・省メモリ化に影響しない

しばしば、TypeScriptとJavaScriptを比較する話の中で、次のような言説が見られます。

  • TypeScriptはJavaScriptより高速に実行できる
  • TypeScriptはJavaScriptよりメモリ消費量が少ない

また逆に次のように心配されることもあります。

  • TypeScriptはJavaScriptで書くより低速になるのでは?
  • TypeScriptはJavaScriptよりメモリ消費量が大きいのでは?

結論を言うと、TypeScriptの実行時パフォーマンスはJavaScriptと同じです。これを理解するには、次の2つの前提をおさえておく必要がります。

  1. TypeScriptのランタイムはない。
  2. TypeScriptコンパイラは最適化しない。

TypeScriptランタイムはない

TypeScriptにはランタイムがありません。どういうことかというと、TypeScriptを直接実行するエンジンがないということです。TypeScriptを開発しているMicrosoftのブラウザMicrosoft Edgeであっても、TypeScriptは実行できません。サーバーのNode.jsもそうです1。TypeScriptで書いたコードを実行するには、一度JavaScriptコードに変換する必要があります。そのため、TypeScriptのパフォーマンスは、コンパイル後のJavaScriptがどうなっているかで決まるわけです。

TypeScriptコンパイラは最適化しない

一般的に「コンパイラ」には、次の3つの仕事があると言われます。

  1. ソースコードを解析し、問題点をチェックする
  2. ソースコードを別の言語に変換する
  3. 最適化する
    • 実行速度が速くなるようにする
    • 少ないメモリで動くようにする
    • 少ない電力で済むようにする
    • 実行ファイルのサイズを小さくする

このうち、TypeScriptコンパイラがするのは上の2つです。3つ目の最適化はしません。TypeScriptコンパイラは、基本的に型に関する部分を消すだけで、それ以外の部分はほぼそのままJavaScriptに変換します。

たとえば、次のようなTypeScriptコードをコンパイルすると、

TypeScriptコード
ts
const oneDay: number = 60 * 60 * 24;
TypeScriptコード
ts
const oneDay: number = 60 * 60 * 24;

次のJavaScriptコードが生成されます。型注釈のnumberが消されただけです。

コンパイル後のJavaScriptコード
js
const oneDay = 60 * 60 * 24;
コンパイル後のJavaScriptコード
js
const oneDay = 60 * 60 * 24;

この60 * 60 * 24の式は静的に計算できるものです。コンパイル時に計算して、次のようなJavaScriptを生成しておけば、実行時の余計な計算が不要になります。高速化に寄与します。

予め計算したJavaScriptコード
js
const oneDay = 86400;
予め計算したJavaScriptコード
js
const oneDay = 86400;

上のような最適化は技術的には可能なはずです。しかし、TypeScriptはこうした最適化は原則的に行いません。TypeScriptコンパイラがするのは基本的に型を外すだけです。

両者のパフォーマンスは基本的に同等

TypeScriptには次の特徴があることを見てきました。

  1. TypeScriptのランタイムはない。
  2. TypeScriptコンパイラは最適化しない。

この2つの特徴から、まったく同じロジックのコードをTypeScriptとJavaScriptで書いて比較したとき、その間には注意が必要なほどのパフォーマンスの違いはないと考えて差し支えありません2

JavaScriptの仕様バグは修正しない

JavaScriptには元々バグだったものが仕様に変わった例があります。たとえば、値の型を調べるtypeof演算子は、nullを渡すと"object"が返ります。これはバグと考えられていましたが、後方互換性のため修正されることなく仕様になりました。

js
typeof null;
"object"
js
typeof null;
"object"

TypeScriptでも、こうした仕様バグは修正されていません。なぜかというと、TypeScriptはあくまでJavaScriptに型をプラスした言語というスタンスだからです。

学びをシェアする

TypeScriptが解決しないこと

・JavaScriptの実行時パフォーマンス改善
・JSの仕様バグの解決

『サバイバルTypeScript』より

この内容をツイートする

  1. TypeScriptのランタイムを謳うDenoというサーバー環境があります。このDenoであっても、内部的にTypeScriptをJavaScriptにコンパイルし、それをJavaScriptエンジン上で実行しています。
  2. 厳密に言うと、コンパイラオプションtargetes3(古いJavaScript)に指定するなどで、「単に型を消すだけ」のコンパイルではなくなる場合もあるので常に同等が保証されているわけではありません。
  • 質問する ─ 読んでも分からなかったこと、TypeScriptで分からないこと、お気軽にGitHubまで🙂
  • 問題を報告する ─ 文章やサンプルコードなどの誤植はお知らせください。