TypeScript の tsconfig.json を 考える

TypeScript で Hello World が できたところで、TypeScript について深堀したいと思います. なにせ、初めて使うものですから… まず tsconfig.json に 何を設定しておいた方がいいのか、考えたいと思います.
今回の検討の前提として、TypeScript の コードはサーバーサイドで使うことを想定しています. ブラウザ内で動作する JavaScript は いったん考慮外としています. また既存のしがらみは無く、新しく作るものを想定しています.

作業環境

  • Windows 10 64bit
  • Node.js 8.4.0 64bit
  • TypeScript 2.4

前回 Hello World の 設定を振り返る

前回の Hello World では Visual Studio Code の 公式ドキュメント の tsconfig.json を基に作成しました. まずは、この内容について振り返りをしたいと思います.

1
2
3
4
5
6
7
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"sourceMap": true
}
}

設定したのはコンパイラーのオプションでだけになります. (よくトランスパイル/トランスパイラーって見聞きして真似てたけど、もしかしてコンパイル/コンパイラーが正しい? ^^;)

target は、TypeScript を トランスパイルする先の、ECMAScript の ターゲット・バージョンになります. es3 が デフォルトで、前回は es5 ECMAScript 5 に 設定していました. Hello World 的にはあまり関係はないのでサンプルのままです. 今後の設定としてはサーバーサイト前提なので 2017年8月現在 最新 の async/await が 使える es2017 になります.

module は、モジュールコードの生成方法になります. Hello World では、もちろん関係ありません… 後々使っていく場合の設定値としては、サーバー再度用途で Node.js で 動かすので commonjs に設定したいと思います.

sourceMap は、 .map ファイルを生成するオプションです. .map ファイルがないとデバッガーはトランスパイルされた .js ファイルを参照するため、 .ts を 見ているエンジニア側とミスマッチが発生します. デバッガーなどのツールに.map ファイルを参照してもらうことで、 .ts ファイルを参照してもらうことができるので、ほぼ必須のオプションでしょう.

tsconfig.json の 仕様について調査

つづいて tsconfig.json の 仕様はどうなっているのか、公式ドキュメント https://www.typescriptlang.org/docs/handbook/tsconfig-json.html から大筋を参照したいと思います.

Overview / Using tsconfig.json

まず、 tsconfig.json がある ディレクトリを TypeScript プロジェクトのルートとして認識するとのことです. tsc を 実行する際に、 tsconfig.json を 関連度ディレクトリから親ディレクトリ方向に探していき使うか、 -p (--project) オプションで tsconfig.json の パスを指定します.

Examples / Details

tsconfig.json の 記述形式は compilerOptions プロパティに続き、 files プロパティ を使用する形式と、 include/exclude プロパティを使用する形式に分かれます.

files プロパティの使用例 (公式ドキュメントから抜粋)

1
2
3
4
5
6
7
8
{
"compilerOptions": { ... },
"files": [
"core.ts",
"sys.ts",
"types.ts"
]
}

include/exclude プロパティの使用例 (公式ドキュメントから抜粋)

1
2
3
4
5
6
7
8
9
10
{
"compilerOptions": { ... },
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}

compilerOptions プロパティについては、省略した場合はコンパイラーのデフォルトが使われ、明示的に指定する場合は Compiler Options を 参照とのこと. 設定項目が多いので後日.

files プロパティは、相対または絶対のファイルパスのリストとのことで、たぶん使うのは面倒くさいので置いとき、 include/exclude プロパティを使うのがよいでしょう.

include/exclude プロパティは、glob のようなパターンで指定できます. glob、Linux などで *.txt* のような “ワイルドカードでファイル名のセットを指定するパターンのこと - グロブ - Wikipedia“ とのことで、こっちで指定する方が便利です. 以下のワイルドカードからパターンを作ります.

  • * 0個以上の文字
  • ? 任意の1文字
  • **/ 任意のサブディレクトリに再帰的にマッチ

files プロパティ と include/exclude プロパティ の 有無や、組み合わせなどの複雑なルールについての記載もあるけど、あまり頑張らないで簡単な構造にしたいのでパスします.

@types, typeRoots and types

@types パッケージは、すべてコンパイルに含まれるとのこと. その制御については compilerOptionstypeRootstypes で できる.
全部入って問題ないような気もします. 使うとしたら、 types で パッケージ (e.g. node, lodash, express) を 明示するのでよさそうです.

Configuration inheritance with extends

tsconfig.jsonextends プロパティを使って別ファイルから構成を継承できます. ベース(継承元) の 設定がロードされて、継承している設定が上書きロードします.
ある程度の規模で複数プロジェクトに分けて構成する場合に便利なので使う機会は結構ありそうです. すぐには使う機会はなさそうですが、このような設定ができることを覚えておくと、後で便利そうです.

compileOnSave

compileOnSave プロパティを設定すると、 tsconfig.json 保存時に すべてのファイルを再生成するように、この機能をサポートしている IDE へ 通知します.
tsconfig.json の 試行錯誤段階ではよさそうだけど、ある程度固まってきたら使わないのかもしれないです. ところで、今回使う Visual Studio Code の 記載がないが対応しているのだろうか?

Schema

スキーマは、ここだよ http://json.schemastore.org/tsconfig って、ことで後で眺める.

サマリ

compilerOptions を どう設定するかがメインになりそう.
後は include/exclude . これは、Java の Maven のように 定番があると嬉しいのですが、サンプル以外に特に具体的なパターンはなかったです. あまり独自のスタイルを作るよりも、定番に乗っかっていきたいところ.

TypeScript を 使っているプロジェクトを調査

Microsoft/TypeScript

TypeScript 自身のリポジトリ. テストケース用なのか tests ディレクトリ以下にかなりの tsconfig.json が あります.
その中から src 以下をいくつか参照したところ、/src/tsconfig-base.json を 継承して作られているようで、こちらは compilerOptions だけなので、後日参照.
継承してる側は files プロパティで列挙でした.

Microsoft/vscode

Visual Studio Code の ベースとなっているリポジトリ. (製品版とは異なるらしい → Visual Studio Code - Wikipedia)
src/tsconfig.json が あり、また extensions/ 以下に各拡張機能用の tsconfig.json があります. 継承関係は無いです..

/build/tsconfig.json では "node_modules/**"exclue 、拡張機能系はファイルが分かれているが大体同じで、 "src/**/*"include でした.

今のところの設定

compilerOptions は 改めて調査するとして、今までのところで作ると以下のような感じでしょうか. って、結局 公式ドキュメントのサンプル…

1
2
3
4
5
6
7
8
9
10
{
"compilerOptions": { ... },
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}


プロジェクトのディレクトリ構造にかかわる設定なので、いろいろと悩んでしまいます. とりあえず公式ドキュメントのサンプルに則って定義しておきたいと思います.
使い込んでみてわかることなのでしょう. きっと.