TypeScript、台頭か

rise_typescript_header
JavaScriptのコミュニティがツールやフレームワークを統合する頻度は、ニコラス・ケイジがいい映画を作るのと同じくらいの頻度です。何が言いたいのかというと、あることはあるのですが、あったとしたら注目を集めるぐらい稀だということです。

だから私は、AngularのチームがAngular 2の開発に使用する言語を自社のAtScriptからTypeScript切り換えるという決断をしたのは非常に興味深いことだと思いました。これまでも、AngularのチームはTypeScriptのチームと共に開発を行ってきてはいますが、直接TypeScriptを使用するという決断は、TypeScriptのプロジェクトを強く支持しているということに他なりません。

また、TypeScriptを活用しているプロジェクトはAngularだけではありません。全くの偶然ですが、私たちTelerikはAngularのチームがこの発表をしたのと全く同じ日に、NativeScriptのパブリックベータをリリースしました。NativeScriptプロジェクトのコアとなるJavaScriptフレームワークCLIは、どちらもTypeScriptで記述されていますし、NativeScriptはTypeScriptのコードを第一級オブジェクトとして扱います。

この数ヵ月間、TypeScriptはこれらの発表による恩恵を受けてきました。実際、”非常に科学的な”Googleトレンドの比較では、TypeScriptはこれらの発表により、JavaScript互換の他のフレームワークよりも多くの関心を集めていることが分かります。

tbbsuzI

なぜ今、TypeScriptなのか

TypeScriptはJavaScript互換言語として初めて開発されたものではありません。むしろ遅い方です。ランタイムとしてのJavaScriptが至る所で用いられているため、様々なプログラミングのバックグラウンドを持つ人々が自分たちの都合のいいようにJavaScriptを改造してきました。実際CoffeeScriptのチームは、JavaScript互換言語を笑ってしまうほどたくさん、なんと250以上も保持しています。そうです、250以上の言語ですよ。これをネタに xkcdコミックに入れてもらえそうなほどぴったりのマンガを描いてみました。

公正を期すためにお伝えしておきますが、これらの言語の中には適当に作られたものや概念実証のために実装され、実際は世間にリリースされていないものもあります(CobolScriptはこれに当たるでしょうね)。しかし多くは開発に多大な労力をかけられ、巨大なエコシステムを持ち、たくさんの企業支援を得ている言語です。ではこれを考慮した上で、TypeScriptを他の多くの言語と差別化しているものとは一体何なのかを考えてみましょう。ここに少し挙げてみます。

差別化要因その1:選択ができる

JavaScript互換のフレームワークは一般的に2つのグループに分類できます。JavaScript上に構築するものと、完全にJavaScriptを放棄したものです。大部分のフレームワークが後者(JavaScriptを完全に放棄している方)に属しますが、TypeScriptはJavaScript上に構築する方を選択しており、Microsoftはこのアプローチの正当性を強く主張しています。以下は以前Microsoftが見解を述べたブログからの引用です。

「JavaScriptには根本的な欠点があり、これらのシナリオをサポートするには、構文及びランタイムでJavaScriptと“完全に決別する”ことが必要であると、Dartなど一部の「JavaScript互換のフレームワーク」が予告しました。私たちは、このような見解には同意しません。委員会の参加者として、標準ランタイムを拡張することも、大規模なJavaScriptのサポートに必要な構文機能を既存のJava標準の上に構築することも可能であると確信しています。」

TypeScriptはJavaScriptのスーパーセットですから、既存の.jsファイルのファイル名を.tsに変更でき、そうすれば基本的にきちんと機能するということです。これはWebデベロッパにはよくあるパターンで、私たちの多くが既に使用しているCSSプロセッサ(例えばSASSやLESSなど)も全く同じように機能します。

有効なJavaScriptがTypeScriptでは有効でないというレアなケースもありますが、こういったケースは大抵の場合、容易に検出し修正できます。

TypeScriptにはオプショナル型システムがあるのですが、JavaScriptの開発者の多くはこれを不要なものだとバカにするかもしれません。しかし多くのサーバ側の開発者は、「神よ感謝します。私には自分の型が必要なのです」と思っています。TypeScriptのオプショナル型システムのすごいところは、自分で選択可能であるという部分です。これは、意味を成す箇所であれば型を使用でき、意味を成さない箇所では除外することができるということであり、各チームがそれを自分たちで決められるのです。

例えば、以下のTypeScriptのコードは2つのローカル変数を数値として定義し、計算の中で使用しています。

var height : number = 2;
var width : number = 3;
console.log( "Area is: " + ( height * width ) );

このような非常にシンプルなシナリオでは、私個人としては型は不要だと思っています。これらの変数を何に使っているのかが非常に明確ですから。TypeScriptは、実際にこの2つの式の右辺からここの型を自動的に推論します。

しかし、あなたがもしこの機能をアプリケーション全体で使えるような関数にリファクタリングしようとしたら(そしてそれがこの簡単な例よりもずっと複雑なものだったら)どうでしょう。そういった場合のアプローチを以下に示します。

function calculateArea( height: number, width: number ) : number {
    return height * width;
}

console.log( calculateArea( 2, 3 ) );

ここではこの3つのnumberの宣言が、この関数は2つの数値型のパラメータを想定していて、数値を返すということをTypeScriptに教えています(最後の:numberは関数自体の戻り値の型を定義しています)。この関数は再利用可能なAPIとして想定されているものなので、型宣言がより有効だと思います。他のデベロッパはこの関数の使い方を学ぶためにこれらの型宣言を利用できますし、これらの型宣言は自分のコードを長期に渡って保守するのにも役立ちます。

TypeScriptはこれらの型宣言をコンパイル時に検証します。つまり、もしこの関数を誤った使い方で用いてしまったら(例えば2つの数値ではなく2つの文字列を渡すなど)ビルドが失敗するということです。以下は、私がcalculateArea( “2”, 3 )をコンパイルしようとした時の、TypeScriptのコマンドラインのインターフェースです。

Rm4Aw57
メンテナンスにはこれが役立つでしょう。関数のAPIを変更する時は型を探すコンパイラが関数の全ての使用箇所を即座に知らせてくれるので、検索と置換に頼る必要がなくなります。

TypeScriptの選択ができるという特徴はこの言語の型システムに関連したものですが、これと同じ設計上の選択が、TypeScriptが提供している全てのものに当てはまります。TypeScriptにはモジュールクラスインターフェース、その他にもいろいろな機能があり、価値があると思えばそれを利用できますし、価値がないと思えば普通のJavaScriptを好きなように使い続ければいいのです。

TypeScriptはオプショナルな型の先駆けではありません。もっと前からDartなど複数の言語がこの機能を持っています。しかしTypeScriptは、設計においてDartとは違う賢い選択をしたのです。それが、JavaScriptに賭けるという選択です。

差別化要因その2: ECMAScriptとの互換性の確保

TypeScriptは常に最新のECMAScriptの仕様をサポートしており、標準から離れた言語を使うことに不安に感じるJavaScript開発者達を安心させてくれます。
例えば直近のTypeScriptのリリースでは、“let”や“const”キーワードと同時に、ES6のテンプレートリテラルをサポートすることが宣言されています。また近々リリースされるバージョン1.5では、ES6のモジュールや、分割代入スプレッド演算子、等の仕様がサポートされます。
TypeScriptの最新バージョンはBabelTraceur(下図参照)のようなES6の仕様を現時点で使用可能にするようなソリューションにはまだ遅れをとっていますが、近々リリースされるTypeScript 1.5ではその差を大きく埋めることが目論まれています。

TjFiOY2
現在のES6互換性(https://kangax.github.io/compat-table/es6より)
TraceurやBabelは新しいJavaScriptの仕様をできるだけ多くサポートすることを明確な目標としていますから、TypeScriptが追いつくのは難しいでしょう。しかしTypeScriptを差別化するのは単に新しいAPIの数だけではなく、上述したような軽量言語的な型システムに加えて新しいJavaScriptの仕様を提供してくれるという点にあるのです。
このような型システムを採用する主な理由の1つは、この型システムがVanilla JSでは使えないあらゆる開発者向けツールの使用を可能する点にあります。実例を見てみましょう。

差別化要因その3: 開発者向けツール

TypeScriptの最も不評だった点の1つは、ずっとicrosoftのVisual Studioでしか開発者向けツールが使用できないということでした。しかしこれも変わりつつあります。例えば最近WebStormがTypeScriptをサポート対象に加えました。またEclipseのプラグインも登場しています。
Sublime Textのユーザとして、私はTypeScriptのプログラムマネージャであるJonathan Turnerがng-confでMicrosoftのSublime Textプラグインを紹介したことに非常に興奮しています。このプラグインはGitHubから取得して試すことができます。(このことを教えてくれた@jasssonpetと@robpennerに感謝します)。これは非常によくできたプラグインで、この記事のスクリーンショットでは全てこれを使用しています。
TypeScriptがどんな開発者向けツールを使用可能にするかを見るために、calculateArea関数に戻ってみましょう。

function calculateArea( height: number, width: number ) : number {
    return height * width;

例えばこのメソッドにcalculateArea( “2”, 3 )のように文字列を渡したとしましょう。TypeScriptはメソッドが期待する型を理解していますから、開発者向けツールを通じてそれを教えてくれます。例えばSublime Textでは下図のようなエラーが表示されます。

giCwLq3
同じように開発者向けツールはメソッドの戻り値の型を取り違えている場合にも知らせてくれます。例えばcalculateArea関数の戻り値を文字列として扱おうとした場合には以下のようなエラーが表示されます。

BrznULB
この記事のスコープからは外れてしまいますが、TypeScriptは他にも多くの機能を持っています。それらを使えば開発者向けツールがよりスマートになります。例えばインスタンスを生成した時にTypeScriptは使用可能なプロパティやメソッドを教えてくれます。

3okKB1k
クラス階層のような、より複雑なシナリオにも対応可能です。

4snpfpZ
私が気に入っているTypeScriptの機能はヘッダファイルです。詳細についてはTypeScriptのドキュメントの説明に任せますが、私に言わせればヘッダファイルは外部ライブラリのコード補完を可能にする手段です。DifinitelyTypedのGitHubリポジトリではダウンロードして使用可能な数百の既存ライブラリのヘッダファイルが提供されています。これらのヘッダファイルはますます知名度を増してきており、Facebook Flowのような静的型チェッカでさえも使用を検討しています
例を示すと、下図のコードはjQueryのヘッダファイルを使用することでjQuery APIのコード補完を実現しています。

olABd9S
このようなコード補完は馴染みのないライブラリを使用する時に特に役立ちます。例えばNativeScriptでは、JavaScriptを使用した全てのiOSとAndroidのAPIへのアクセスを提供しています。これは非常にスマートなのですが、残念なことに私はAndroidの開発者でもなければiOSの開発者でもないので、どんなAPIがあるのか分かりません。しかしNativeScriptはTypeScriptのヘッダファイルを提供しているので(このリポジトリにあるandroid17.d.tsとios.d.tsを見てください)、簡単に扱うことができます。下のgifではiOSとAndroidのAPIをSublime Textで探しています。

dmKU74M
まだまだ紹介できる機能はたくさんありますが、これまでお見せしてきたものがTypeScriptを他のJavaScript互換言語と差別化する主な機能だと考えています。こういった機能を持っているのはTypeScriptに限りません。例えばDartもオプショナル型システムを備えていますし、他の多くの言語も開発者向けツールを念頭に置いて記述されています。TypeScriptはこれらの機能を複合的に備えているという点で考慮に値する言語なのです。

TypeScriptは成長するか?

Angularの声明はTypeScriptの誇大広告と言えなくもありませんが、私にとって一番興味深いのはこのような誇大広告が「実際に使えるものになるのか」ということです。いくつかのJavaScript互換のフレームワークはファンを獲得しましたが、一つとして主流になることはできませんでした。例えばよく引用されるTIOBEプログラミング言語ランキングではJavaScript互換言語はトップ50に1つも入っていません。CoffeScriptとDartは50位から100位の間に入っていますが、TypeScriptはランク外です。
JavaScript互換言語が非主流であるさらなる証拠を示すなら、前に示したGoogleのトレンドグラフに既に主流となっている言語であるSASSを加えてみましょう

wnPCH9V
SASSがどんどん有名になっていくのは非常に興味深い出来事です。5年前に私はJavaScript互換のフレームワークは浸透しないと主張しました。なぜならフロントエンドの開発者は自分のアプリにビルドの手間をかけるのを望まないと考えたからです。しかし今日ではGruntやGulpのようなタスク実行ツールが広まり、ビルドの実行が当たり前になりました。SASSが浸透したことは、フロントエンドの開発者がもはや開発のワークフローにビルドという手順を組み込むことを気にしなくなったのです。そうであるならば、Web開発者がCSSのプリプロセッサは使うけれどもJavaScriptのプリプロセッサは使わないなどと言うことはできないでしょう。

CSSはJavaScriptよりも短所が多いのだから、プリプロセッサの使用も多くなるのだと主張することはできるかもしれません。しかし私の経験上、それは間違いです。経験上、CSS嫌いと同じくらい多くのJavaScript嫌いが存在しますし、少なくとも両者に大きな違いはありません。

私の理論を述べましょう。CSSとは違い、JavaScriptはアプリのためのロジックを持つので、プログラマはそのロジックがどのように記述されるかについてより確固たる意見を持っています。開発者は、すでによく知っている慣習に従ってWebコードを書きたいと思うものです。CoffeeScriptはいくつかのRuby的な考え方を借用しているため、Rubyコミュニティでとても人気があります。TypeScriptは、C#を書いたのと同じ人物によって開発され、C#コミュニティで多くの支持を得ています。このように意見や文法が分かれてしまうために、これらのプリプロセッサは複数のコミュニティをつなぐことができず、うまくいかないのです。

なぜTypeScriptは特別であり得るのか

正直に言いましょう。私は、昔からJavaScript互換のフレームワークが不要だと思っているWeb開発者の1人です。神が意図されるように、私はJavaScriptは純度の高いものであってほしいのです。例えばBabelのように、型とか開発者向けツールのようなものを持ち出すものより、できるだけJavaScriptに忠実なままのプリプロセッサに、はるかに興味があります。

しかし、TypeScriptは、私がすぐに却下しなかった初めてのプリプロセッサです。JavaScript上に構築されるというミニマルなアプローチは驚くほど魅力的ですし、ECMAScriptの仕様を堅守しようとする姿勢にも信頼が置けます。ですが長きに渡ってavaScriptを用いてきた開発者として、思い切ることにためらっています。Douglas Crockfordは、 TypeScriptについてのコメントの中で、私が感じていることを見事に要約してくれています。

MicrosoftのTypeScriptは、多くのJavaScriptのフロントエンドの中で最良であるかもしれません。一見、最も魅力的なコードを生み出すように思われます。また型宣言やクラスのような新しい機能に対するECMAScriptの仕様の圧力を軽減するものだと思います。Andersはこういった新仕様に対する対応はプリプロセッサでうまく提供されることができることを示したので、もとの言語を変える必要がありません。

型指定の甘さはJavaScriptの最大の長所の1つです。また型チェックは過大評価されすぎだと思います。TypeScriptは甘いですが、その甘さには代償が伴っています。私はその代償を払いたいとは思いません。

私自身はTypeScriptを積極的には受け入れられませんが、我々JavaScriptコミュニティの人間ばかりがJavaScript互換言語の対象ではないでしょうし、実際TypeScriptは幅広い開発者にとって魅力的なものだと思います。

興味深いことに、CrockfordはCoffeeScriptについて、うまいことを言っていました。JavaScriptのコミュニティは市民権を得ているのに、CoffeeScriptはまだ主流とは言えません。それでは何がTypeScriptを別格にするのでしょうか? それはおそらくMicrosoftとAngularです。

CoffeeScriptはRubyコミュニティではうまくいきましたが、それ以外のコミュニティへ脱することはなかなかできませんでした。TypeScriptは現在MicrosoftとAngularのサポートを得ています。この2大勢力がTypeScriptに巨大な開発者のコミュニティをもたらしています。TypeScriptが、どうにかして両方のコミュニティで定着できたならば、おそらくJavaScript互換のフレームワーク初の主流になることができるでしょう。

さらに、増加傾向のES6に対する人気を考慮すべきでしょう。ES6が力を得るにつれ、ますます多くのプログラマがJavaScriptの新機能を使うことができるツールを探すことになるでしょう。TypeScriptによってES6を今使用することができるようになりますし、その型システムは他のJavaScript互換のライブラリとは違う開発者向けツールを提供してくれるのです。それは大規模な普及につながるでしょうか? それは時間が教えてくれるでしょう。

TypeScript参考資料

TypeScriptを勉強し、本記事を書くにあたり、良質な記事と参考資料を見つけました。以下がその資料です。

*TypeScriptハンドブック
*PluralsightにおけるTypeScriptの基本
*ng-confカンファレンスからAngular におけるTypeScriptについてJonathan Turnerの講話
*ひと息で分かるTypeScriptのワークフローの作り方

ヘッダー画像はNBphotostreamのご好意より