👨‍⚖️

なんで JavaScript ではなく TypeScript を使うのか?

2023/05/04に公開

この記事の目標

「最終的に JavaScript になるのに、なんでわざわざ TypeScript を使うべきなのか? JavaScript で良くない?」 という質問に答えられるようになる

なぜ TypeScript を使うべきなのか?

いきなり結論を書きます。

A. 実行時エラーの少ない JavaScript を使いたいから

TypeScript で書かれたコードはコンパイルが通らないと JavaScript に変換できません。そのため、生成される JavaScript コードは必ずコンパイルに成功したものです。コレが TypeScript を使っていて一番嬉しいポイントです。

TypeScript コードをコンパイルしてできる JavaScript のコードは全体の部分集合

まあ、いきなり結論を書いてもよく分からないと思います。順に話していきます。

型エラーとはなにか

TypeScript でコンパイルを通すには、コード上の型エラーを無くす必要があります。

型エラーとは、型システムの typing rules に従っていない箇所のこと です。

typing rules を説明すると長くなるので、カンタンな例を提示します。雰囲気を感じ取ってください(良くない)。

  • number + numbernumber 型に簡約される
    • e.g. const five: number = 3 + 2
  • 関数の型 (arg: string) => number があり、その関数に string を渡して呼び出すと number 型に簡約される
    • e.g. Number("42") は number 型

TypeScript で書かれたコードはすべて typing rules の範疇で書かれていなければコンパイルが通りません。逆に、typing rules に則ってコード全体を書いていればコンパイルできます。

typing rules に従っていないコード例

以下に typing rules に従っていない、型エラーが出るコードの例をいくつか挙げます。

たとえば 'めちゃ' * 2 という式は型エラーになります。なぜなら TypeScript の typing rules に string * number をどう簡約するか定義されていないためです。

他の型エラーの例:

  • const showsButton = true; showsButton() (boolean 型を関数呼び出しできない)
  • (42).prop (number に prop というプロパティは存在しない)

これらはいずれも TypeScript の typing rules の範囲で解釈できないので型エラーです。

余談: 型エラー != 実行時エラーが起きる

型エラーの例にあげた "めちゃ" * 2 は実行時エラーが起きません。NaN になります。

"めちゃ" * 2 の計算結果

(42).prop も undefined になります。実行時エラーは起きません。

このように、型エラーになった箇所で実行時エラーが必ず起きるわけではありません。

とはいえ、NaN になってしまうような計算も存在しないプロパティへのアクセスもさほど意味がありません。typing rules で許容しないままで良いと筆者は思います。

(さらに余談: const showsButton = true; showsButton() は型エラーが出て、実行時エラーも起きます)

型エラーが少ない JavaScript だと何が嬉しいのか?

TypeScript コードをコンパイルしてできる JavaScript のコードは全体の部分集合だと言いました。つまり自由度が低いわけです。「なら尚更 JavaScript を書いた方が良いのでは?」と思われる方もいるかもしれません。

しかし、例えば 「法律がないほうが自由に行動できて最高!」なんて訳ないですよね? 自由度の高さ = 良いわけではありません。

TypeScript も同じです。TypeScript は JavaScript を制限して秩序を生んでいるのです。 型システムという規律が自由すぎて混沌とした JavaScript に秩序をもたらすのです。

例えば上に書いた boolean 変数を関数呼び出ししようとして実行時エラーが起きる (showButton()) なんて誰も望んでいません。制限された方が嬉しいですよね。NaN になる 'めちゃ' * 2 という計算も出来なくて問題ありません。

余談: 実行時エラーが完全になくせるわけではない

TypeScript は気を抜くとすぐに実行時エラーが紛れ込みます。

const savedData: {data: number} = JSON.parse(localStorage.getItem('saved item') ?? '');
// ↑ JSON.parse の返り値は any なので {data: number} 型である保証はない

savedData.data; // もし savedData が null だったら実行時エラーが起きてしまう!

このコードは残念ながらコンパイルが通ってしまいます。

きちんと適切に TypeScript を使っていないと実行時エラーが出る可能性は依然としてあるままです。気を付けましょう。

他の TypeScript を使う利点

TypeScript を使っているとコード補完でも恩恵を受けられます。Tailwind css を書いているとよく分かると思います。エディタがクラスを提示してくれて選ぶだけ、しかも存在しないクラスを書いていたらコンパイル時に分かるというのは TypeScript ならではです。

まとめ: TypeScript は秩序ある JavaScript

TypeScript は自由度の低い JavaScript ではなく、typing rules という法によって秩序がもたらされた JavaScript なのです。Typing rules 万歳!

Discussion