VSC:TypeScript:Visual Studio Code でコンパイル

プロジェクトを作ろう

 前回はVisual Studio Code(以下VSC)の設定をいじくり回すだけで終わっちゃったので、今回やっとTypeScriptを実際にプロジェクトを作って動かそう、という段階です。
 基本的なことは、Visual Studio Communityってページからリンクされてる日本語の資料Visual Studio Code ファースト ステップ ガイド(PDF)にTypeScriptのコンパイル方法が書いてあるので、まずはそちらを読むと良いかと。

 例によって、より詳しい情報はVisual Studio Code - Tasksあたりを参照のこと。

とにかくコンパイル

 Visual Studio Code ファースト ステップ ガイド(PDF)に書いてある内容を抜粋。
 5. Visual Studio Code を用いた TypeScript アプリケーションの開発がそれだ。

 まずはTypeScriptの環境構築だが、TypeScript:とりあえず入門してみるで既にコンパイルできるようになっているので問題ない…と思ったら、パッケージマネージャのtsdも入れます、とか書いてあるので素直に従う。
 Node.jsを入れてsudo npm i -g typescriptするところまではやっているので、今回はsudo npm i -g tsdをする。

 VSCは基本的にプロジェクトに必要なファイルをまとめたフォルダを開いて、コードを書くようになっている。
 なので、まずはFinderでもターミナルでもいいので適当なフォルダを作って、VSCから[File]-[Open]する。
 するとウインドウ左側の一番上のアイコン(EXPLORE)に今開いたフォルダが大文字で表示されてる。
 その上にポインタを持ってくるとアイコンが表示される、一番左が新規ファイルなので、sample.tsとか適当な名前でTypeScriptファイルを作る。
 ウインドウ右下のファイルタイプがちゃんとTypeScriptになっているのが確認できる。

 ここで、コードを書くとちゃんとコード補完(インテリセンス)が働いていることが確認できる。
 基本的な構文エラーは書いた時点でリアルタイムに指摘される(下波線がつく)
 でま、テキトーにスクリプトを書く…とりあえずは書かなくてもいいけど。

 ここでコマンドパネルを開いて(デフォルトだとshift+cmd+p)、Tasks:Configure Task Runnerを実行。
 すると.settingsフォルダとtasks.jsonファイルが作られる。
 tasks.jsonは、プロジェクトで実行されるコンパイルとかデバッグなどタスクの設定を書いておくファイル。

{
	"version": "0.1.0",

	// The command is tsc. Assumes that tsc has been installed using npm install -g typescript
	"command": "tsc",

	// The command is a shell script
	"isShellCommand": true,

	// Show the output window only if unrecognized errors occur.
	//
	"showOutput": "silent",

	// args is the HelloWorld program to compile.
	"args": ["HelloWorld.ts"],

	// use the standard tsc problem matcher to find compile problems
	// in the output.
	"problemMatcher": "$tsc"
}

 コメントアウトされていない箇所は上記のように書いてある。コメントアウトされている部分はサンプルなので、参考にしつつ書き換えた後は削除していい。
 tasks.jsonの中身は、コメントでも解説してあるが、それぞれのデータ名の上にポインタを持って行くと出るヘルプでも解説される。
 keybindings.jsonもそうだったが、VSCの設定関連のJSONは、インテリセンスやスニペットその他のエディタの挙動がそれぞれ異なる。

 で、ざっと言うと、このファイルはtscというシェルコマンドをサイレントモード(エラーが出ない限り結果を表示しない)で、引数"HelloWorld.ts"として実行し、エラーなどの問題があった場合は、$tscに渡す。ということが書いてある。
 $tscはVSCで用意してある設定の一つで、他の用意してある設定やユーザ設定とかあるみたいだけど、ひとまずTypeScriptのコンパイルしかしないから、他の設定は気にしない。
 コメントアウトされてる例の最後にproblemMatcherの書き方の例がある。エラー出力を正規表現でマッチングして、適当なフォーマットの文字列に変換して出力、してるみたい。…この設定を自分で作ることはなさそう。

 で、さっき作ったファイルはHelloWorld.tsじゃなくて、sample.tsなので、argsのところを書き換える。
 んで、tasks.jsonに書いた内容は、コマンドパネルからTasks:Run Build Taskを実行。デフォルトではCmd+Shift+Bに設定されている。
 やってみるとビルド済みのsample.jsが作られた。
 素晴らしい、順調です。

tasks.jsonのサンプルを見てみる

 tasks.jsonにはコメントアウトされている設定があるので、とりあえずそれを一通り見てみる。
 二つ目は、"args": ["-p", "."],の部分が異なる。
 -pは--projectの略記で指定フォルダに含まれるプロジェクト(基本的にはTypeScriptファイルをすべて)をコンパイルする。
 この設定が基本で、さっきの設定のように目的のファイルを直接書くという方式は実際はまず使わないだろう。
 プロジェクト用の設定ファイル(tsconfig.json)をプロジェクトのルートに用意して、そこにコンパイル設定を書いておく必要がある。
 これは、TypeScript1.5から使えるらしい。
 詳細はtsconfig.json · Microsoft/TypeScript Wiki · GitHubを参照のこと。
 要はtscのオプションをまとめて書いておくファイル、ということらしい。
 tsconfig.jsonは、例えば次のような感じに書く。

{
	{
	"compilerOptions": {
		"target": "ES5",
		"module": "commonjs",
		"sourceMap": false
	}
}

 tasks.jsonの三つ目からは、tscじゃなくてgulpとかjake、msbuildの例。まーこの辺もTypeScriptやる分には必要ないのかな。多分。

複数のタスクを書く

 tasks.jsonは見ての通り複数形なので、当然複数のタスクを記述できる。
 さっきのコメントアウトされてた例の中にtasksって設定が書かれているものがある。
 どうもtasksの中に、個別の設定をならべることで、複数の動作を記述できるらしい。
 なるほど、これでHTMLをブラウザで表示したりとかの設定を記述できるのだな!!
 と思っていろいろいじくってみたけど、tasks.jsonに書けるcommandはひとつだけで、tasks設定の中にはcommandを個別に書けないみたい。
 えー、なんじゃそれ。どういう状況を想定しての仕様なんだこれは???
 commandの部分に自前のシェルスクリプトを書いて、その中でいろいろと分岐を書けば、いろいろな動作を記述できるんだろうけど、そういう使い方を前提にしているような雰囲気はない。
 一応作ってみたら確かに動くんだけど、間違ってる感が強い。

 一応、現在開いているファイルをSafariで開く設定を作ってみた。
 commandの部分がひとつしか設定できないから、これとさっきのtscによるコンパイルのタスクを並記できない。

{
	"version": "0.1.0",
	"command": "open",
	"isShellCommand": true,
	"showOutput": "silent",
	"args": ["-a","safari","${file}"],
	"problemMatcher": "$tsc"
}

 problemMatcherを設定しておかないと、出力ペインが開いてしまうので、ダミーとして書いている。
 ${file}は現在開いているファイルを示す、他に${workspaceRoot}: ルート、${fileBasename}:現在開いているファイルの(拡張子を除く)名前、${fileDirname}:現在開いているファイルのディレクトリ、${fileExtname}:現在開いているファイルの拡張子、${cwd}:現在のディレクトリ、とういのがある。

 で、次のようにargsは個別に書けるから、同じコマンドでの動作の違いは幾つも書ける。

{
	"version": "0.1.0",
	"command": "tsc",
	"isShellCommand": true,

	"showOutput": "silent",
	"tasks": [
	{
		"taskName" : "build",
		"isBuildCommand": true,
		"suppressTaskName": true,
		"args": ["-p", "."],
		"problemMatcher": "$tsc"
	},
	{
		"taskName": "watch",
		"isBuildCommand": false,
		"showOutput": "always",
		"isWatching": true,
		"suppressTaskName": true,
		"args": ["-w"],
		"problemMatcher": "$tsc"
	}
	]
}

 うーむ、なぜcommandもタスク別に書けるようにしてないのか。
 evalをcommandに指定すればいいのかと思ったが、どうもうまくいかない。
 それはともかく、複数書いたタスクの選択方法だが、コマンドパネルからTasks:Run Taskを実行すると、設定したtaskNameの値が並ぶので、そこから実行したいものを選ぶという手順。
 isBuildCommandをtrueに設定しているタスクは、Tasks:Run Build Taskで実行できる。

シェルスクリプトで分岐する

 対処方法として間違っている気がプンプンするのだが、一応作ったので紹介しておく。
 Tasks:Run Taskで複数の設定から選んで実行できる。
 まず、tasks.jsonを次のように記述する。

{
	"version": "0.1.0",
	"command": ".settings/tasks.sh",
	"isShellCommand": true,
	"showOutput": "silent",
	"tasks": [
		{
			"taskName": "build",
			"isBuildCommand": true,
			"args": [ "build" ],
			"problemMatcher": "$tsc"
		},
		{
			"taskName": "brows",
			"args": [ "brows", "${file}" ],
			"problemMatcher": "$tsc"
		}
	]
}

 シェルスクリプトはcommandを見れば分かる通り、.settings/tasks.shに製作した。
 で、argsを変えてtasksの中を設定。

 以下は、tasks.shの内容。与えられた引数で分岐して実行するという単純なスクリプト。

#!/bin/sh
if [ $1 = "build" ]; then
	tsc -p .
elif [ $1 = "brows" ]; then
	open -a safari $2
fi

 これだけで対処できることをエディタ本体の機能として実装していないのは、Windowsとその他の環境での差を最小限にしようという方針でもあるのかな。ありそうだな。
 もうちょっと頑張れば、現在編集中のHTMLをサーバにアップロードするとか書けると思うが、好きな人はやってくださいという感じか。
 とりあえず、エディタ上でシェルスクリプトを呼び出す方法は、このtasks.jsonを介するしかなさそう。
 特例として、gitのコマンドに関しては、コマンドパネルから実行できるみたいだけどね。

追記。
 sh -cでシェルを立ち上げて、コマンド渡してやればいいんじゃね? と思ってやってみたらできた。

{
	"version": "0.1.0",
	"command": "sh",
	"isShellCommand": true,
	"showOutput": "silent",
	"tasks": [
		{
			"taskName": "build",
			"isBuildCommand": true,
			"args": [ "-c", "tsc -p ." ],
			"problemMatcher": "$tsc"
		},
		{
			"taskName": "brows",
			"args": [ "-c", "open -a safari ${file}" ],
			"problemMatcher": "$tsc"
		},
		{
			"taskName": "makeDoc",
			"args": [ "-c", "typedoc --out doc . -m 'commonjs' -t 'ES5'" ]
		}
	]
}

 この程度のことで回避できるなら、ますますtasksにコマンドを個別に記述できないのが謎だ。

デバッグとか

 VSCは今のところNode.jsかmonoにしか対応していないということで、TypeScriptに関してはお好きなクライアントでデバッグしてね、ということらしい。
 それ、TypeScriptのデバッグじゃなくてJavaScriptのデバッグじゃん!!

 commandにはシェルコマンド以外に外部プログラムを指定できるそうだが、具体的に何が指定できるのかよくわからない。
 あとはgitについて書くかもしれないし書かないかもしれない。…多分書かない。
 そろそろ、ちゃんとコードを書かないと、環境設定だけで一生が終わってしまう。

 今日はここまで。