一角獣は夜に啼く

ただの日記です。

思ってることとか考えたこととか適当に書きます。 主にソフトウェア開発の話題を扱う 「ひだまりソケットは壊れない」 というブログもやってます。

ユニバーサルアプリの共有プロジェクトで TypeScript がサポートされていない問題の対処法 (Visual Studio 2013)

Windows 8.1Windows Phone 8.1 の両方のプラットフォームを対象にしたユニバーサルアプリ (Universal App) を開発する際、両方のプラットフォームで共有されるアセットは共有プロジェクト (Shared project) に置くことができます。

当然ながら、両方のプラットフォームで共通の JS ファイルも共有プロジェクトに置くことになります。

問題 : 共有プロジェクトでは TypeScript がサポートされていない

さて、先日 「Visual Studio Community 2013 を使用して Windows ストアアプリを TypeScript で記述する」 に書いたように、Visual Studio 2013 では TypeScript がサポートされています。 ユニバーサルアプリの開発でも TypeScript を使いたいですよね。 共有プロジェクトに JS ファイルを置くのであれば、自然と TypeScript ファイルも共有プロジェクトに置きたくなるはずです。 しかし残念ながら共有プロジェクトでは TypeScript がサポートされていません。

GitHub の TypeScript リポジトリにも Issue として立っていたりします。

次善策 : 別プロジェクトで TypeScript をコンパイル

次善策として使われているのが、『別プロジェクトで TypeScript をコンパイルして、コンパイル結果の JS ファイルを共有プロジェクトに出力する』 という方法です。

具体的な流れ

まずは、ソリューションに TypeScript をビルドするための新たなプロジェクトを追加しましょう。 プロジェクトの種類はなんでもいいのですが 「HTML Application with TypeScript」 を使うのが一番手軽で良さそうです。

f:id:nobuoka:20150424174803p:plain

プロジェクトの名前と場所はどこでもいいのですが、ユニバーサルアプリのためのプロジェクト群に揃えておくと良さそうです。 プロジェクトを作った直後のソリューションの状態は次の画像のような感じになります。

f:id:nobuoka:20150424175031p:plain

TypeScript 以外のファイルは不要 *1 なので、それらのファイルは削除しちゃって大丈夫です。

続いて TypeScript のビルド結果を共有プロジェクトに出力するための設定を行います。 先ほど作成したプロジェクトのプロパティを開き、「TypeScript Build」 のタブで 「Combine JavaScript output into file」 にチェックを入れ、出力先 JS ファイルのパスを入力します。 $(SolutionDir) という変数 (?) がソリューションのディレクトリパスを表すので、そこから先の共有プロジェクトの中の好きな場所のパスを入力してやりましょう。

f:id:nobuoka:20150424175533p:plain

これで TypeScript のビルド結果が共有プロジェクトのディレクトリ中に出力されるようになります。 デフォルトではプロジェクトに含まれていないファイルは Solution Explorer に表示されませんが、「Show All Files」 ボタン (下図の赤丸) をクリックすることでプロジェクトに含まれていないファイルも表示されるようになります。

f:id:nobuoka:20150424180025p:plain

あとは、TypeScript のビルド結果のファイル (今回の例の場合だと 「shared.js」 と 「shared.js.map」) を右クリックして 「Include In Project」 することでプロジェクトに含めれば完了です。 このようにすることで、共有プロジェクトに置く JS ファイルを TypeScript で書くことができるわけです。

デメリット?

今回の例では、全 TypeScript ファイルを 1 つの JS ファイルにまとめてしまっているので、JS ファイルを分けたい場合にはちょっと困ります。 もちろん設定しだいで TypeScript ファイル 1 つに対して JS ファイルも 1 つ出力するようにもできますが、その場合は TypeScript のファイルを新たに作るごとに、共有プロジェクトの方で JS ファイルをいちいちプロジェクトに含めるようにする必要があってちょっと面倒そうです。

JS ファイルを 1 つにすることで問題になるのはパフォーマンス周りだと思いますが、まあパフォーマンスが問題になるような規模になることはそうそうないんじゃないかなーというのが個人的な見解です。 問題になるようならそれはそれで TypeScript のプロジェクトをいくつかに分けるという手もありますし。

ここら辺 Visual Studio 2015 でいい感じに扱えるようになってると嬉しいですね。 (Visual Studio 2015 は全然触ってないのでどんな感じになるかわからないです><)

*1:というかもともとある TypeScript のファイルも不要っちゃ不要