さて、あなたはこの TypeScript の本を開くことに決めたわけですが、それは一体全体なぜでしょうか?当ててみせましょう。

多分、JavaScript のエラーメッセージが表示する「undefined には blah というプロパティは存在しません」というわけのわからない警告に嫌気がさしたからでしょう?そうじゃないなら、どこかで TypeScript を使うことによってアプリケーションが大きくなってもうまく code をスケールさせることができると聞いたけれど、でも本当にそんなことできるのか?と疑心暗鬼だからですね。もしくはあなたは C# のエンジニアで、JavaScript 自体を使ったことがないので TypeScript から JavaScript を始めてみようと考えている。そうでもないなら、あなたは関数型のプログラミングを実践していて、その技術を TypeScript によって一歩進めようと決断したから。最後の可能性としては、あなたが書いたコードにエラーが発生することにイラついた上司が、お中元がわりに送りつけたから。(技術上の問題を技術で解決しようとするあなたの上司は、ましな上司ランキングで相当上の方に位置するはずですよ)

あなたがこの本を開いた理由がなんであれ、それはどれも全て正しいと言えるでしょう。TypeScript は次世代の Web アプリケーション、モバイルアプリケーション、それから NodeJS プロジェクト、IoT デバイスを強く押し進めることができるエネルギーなのです。あなたが書くプログラムをより「安全 = safe」にし、よくあるミスを発見し、コード自体にドキュメントとしての機能を与え、リファクタリングの苦痛を取り除きます。(ただし、効果的に使われていればの話ですが。TypeScript を使ってファッキンクソコードを書くことも当然可能ですので)TypeScript を使うことで、あなたの生産性は2倍になり、身長が伸び、腹筋が割れ、スタバの魅力的なバリスタとのデートが約束されます。

でもきっとスタバに向かう交差点で、こんな考えが頭に浮かぶことでしょう。「安全 = safe だと言っていたけれど、それってどういうこと?」私が言っているのはもちろん「型安全 = type safety」のことです。

Type safety とはつまり「型を用いることによって、正しくない動作をプログラムが実行することを防ぐ」ことです。

正しくない動作の例をあげましょう。

  • number 数値と list 配列 を掛け算すること。
  • ある関数の引数はオブジェクトの配列でなくてはいけないのに、引数に文字列の配列を与えて、その関数を実行すること。
  • ディレクトリの位置を最近変えた module であるにも関わらず、そのままのパスで import すること。

こういったよくある間違いに対しても、多くのプログラミング言語はベストを尽くそうとします。プログラミング言語は、あなたが指示した正しくないコードに対して健気にも本当はどうしたかったのかを汲み取ろうとします。だってあなたはきっと正しいことを指示しようとしたわけでしょ?って彼は考えているわけですから。JavaScript ではこんなふうになります。

javaScript の場合
3 + [] // 文字列の '3' として評価される

const obj = {}
obj.foo // undefined として評価される

const a = (b) => {
  return b/2
}
a("z") // NaN として評価される

よくわかったと思いますが、JavaSript は明らかに正しくない操作に対してもベストを尽くそうとし、exception を投げないことができるのであれば、投げません。さて、JavaScript は優秀なのでしょうか?間違いなく優秀でしょう。でもバグを見つけるのが簡単かどうかでいうと、どうでしょうか?多分、簡単ではないはずです。

もし JavaScript が、こういった無効な指示に対して、静かにベストを尽くすのではなく、exception を投げてくれるとしたらどうでしょうか。きっと以下のようなフィードバックを得られるはずです。

すぐに exception を投げる JavaScript だったら
3 + [] // Error: 本当に数値と配列を足し算したいですか?

const obj = {}
obj.foo // Error: "foo" という property を obj に定義するのを忘れていませんか?

const a = (b) => {
  return b/2
}
a("z") 
// Error: function "a" は引数として数値を期待していますが、 
// あなたは文字を渡していますよ。

誤解して欲しくないのですが、私たちが犯したミスをなんとかうまいことやってくれるというのは、プログラミング言語が持つべき良い機能です。(私たちの人生のもこの機能があったらいいのに!)しかし JavaScript に限って言えば、この機能のせいで、間違ったコードを書くタイミングと、その間違ったコードを発見するタイミングが分断されてしまうのです。結果として、あなたのミスは、他人の報告書の中で発見されます。

ではここで問題です。JavaScript があなたの犯した過ちを指摘するのは、いつでしょうか?

そうです。そのコードを「実際に実行した時」なのです。あなたのコードが実際に実行されるのは、試しにブラウザを開いて実行させたときや、他のユーザーがあなたのサイトを訪れたときや、あなたがユニットテストを実行したときです。あなたが十分に規律を重んじる人間で、豊富なユニットテストと end to end テストを書き、ユーザーにコードが届く前にテストをおこなう習慣を持っていれば、ユーザーよりも先にエラーを見つけることができるでしょう。でもそうじゃない場合には?

さあ TypeScript の出番です。TypeScript の素晴らしい点は、有益なエラーメッエージを与えてくれるだけではなく、それを「与えてくれるタイミング」にもあります。TypeScript はエラーメッセージを「テキストエディター」に入力した瞬間に表示してくれるのです。実行するよりも前にです。なので、エラーを見つけるために必ずしも unit test や somke test や同僚に頼らなくてもいいということを意味します。TypeScript がそれをみつけ、あなたに報告してくれるのです。しかも書いている時に。では実際に TypeScript がなんと言ってくれるか見てみましょう。

すぐに exception を投げる JavaScript だったら
3 + [] 
// Error TS2365: Operator '+' cannot be applied to types '3' 
// and 'never[]'. 

const obj = {}
obj.foo

// Error TS2339: Property 'foo' does not exist on type '{}'. 

const a = (b) => {
  return b/2
}
a("z") 
// Error TS2345: Argument of type '"z"' is not assignable to // parameter of type 'number'. 

こういった種類の型に関係するバグを根絶できることに加えて、TypeScript はあなたがコードを書く考え方そのものを完全に変えてしまうことでしょう。以前は値のレベルでしか考えていなかったのに、TypeScript を使うことで、型のレベルでプログラムの概要を思考していくことができるようになります。エッジケース、つまり想定外の処理についても、場当たり的な処理ではなく、あなたがその言語を作ったかのように設計していくことができます。TypeScript はあなたのコードをより簡潔、迅速で、可読性と保守性の高いものにしてくれるのです。

旅の準備はできましたか?さあ出発です!