概要
https://www.typescriptlang.org/tsconfig#rootDirs
{
"rootDirs": ["src/views", "generated/templates/views"]
}
複数のディレクトリを仮想的にマージして、一つの基準のディレクトリとみなしてコンパイルできるようにします。
仮想的なマージなので、このオプションは実際に出力する JS にはなんら影響を及ぼしません。
詳細
基本的にこのオプションが有効なのは、型定義ファイルをコードから自動で生成している場合です。
仮想的な root directory
rootDirs
で複数のディレクトリを指定すると、仮想的にそれらのディレクトリを一つのディレクトリにマージしてimport
を解釈してくれます。
src/
├── dir1
│ ├── hoge
│ └── piyo
│ └── piyopiyo
└── dir2
├── hoge
│ └── hogehoge
└── piyo
↑ 例えばこういったディレクトリ構造があったとして、dir1
とdir2
を以下のようにrootDirs
に指定すると、
{
"rootDirs": ["src/dir1", "src/dir2"]
}
TypeScript コンパイラは root directory を以下のようなディレクトリだとみなしてコンパイルを実行します。
src/
└── dir1
├── hoge
│ └── hogehoge
└── piyo
└── piyopiyo
つまり、同じ名前のディレクトリが同じ階層に存在している場合、実際は別のディレクトリであっても同じディレクトリだとみなす、ということです。
これは、型定義ファイルをコードから自動生成している場合に役立ちます。
例えば
例えば、typed-css-modulesという、CSS Modules を使う際に CSS の型定義ファイルを自動で作成してくれるツールがあります。
こちらを使用していると基本的に全 CSS ファイルと同じ階層に必ず.css.d.ts
ファイルが生成されるわけですが、何気にファイル数が増えてしまうんですよね。
こういう時に、自動生成される型定義ファイルを手で修正を加えるディレクトリとは別のディレクトリに入れるようにしておき、その両方をrootDirs
で指定することで、機能を果たしつつ更新頻度の高いディレクトリをすっきり保つことができます。
と思っていたら、開発者ご本人が解説されているのを発見したのでご紹介しておきます。
TypeScript 2.0 の Module Resolution Enhancements について - Qiita
自動生成されるコードは手で修正を加えるとめんどうなことになる(もしくは無駄足になる)ことがほとんどだと思うので、
- 手で修正を加えるディレクトリ
src/
- 自動生成されるディレクトリ
generated/
- コンパイル結果が入るディレクトリ
dist/
のような区分ができるのはかなり気持ちいい感じがしますね。
後からジョインしたメンバーにも「どれが自動生成でどれが手動修正なのか」がわかりやすいなどのメリットもあると思います。
(自動生成のコードを知らずに手で修正して「ビルドするとなぜか修正が消える…」みたいなことをやった経験ある)
ちなみに、前提となる型定義ファイルについて
TypeScript では、TS(.ts
)ファイル以外をimport
する時、指定されたディレクトリにある型定義(.d.ts
)ファイルの型を読み込みます。
src/
├── hoge.ts
├── index.ts
└── piyo.js
// hoge.ts
export const hoge = "HOGE";
// piyo.js
export const piyo = 123;
// index.ts
import { hoge } from "./hoge";
import { piyo } from "./piyo";
console.log(hoge.trim());
console.log(piyo.trim()); // piyoはnumberなので、trimプロパティを持たないが...
↑ 例えばこういったファイル群があったとして、これをこのままコンパイルすると、エラーなくコンパイルできてしまいます。
piyo.js
に型定義ファイルが存在しないので、piyo
がany
型になるからですね。
ただし、もちろん上記の通りpiyo
はnumber
でtrim
プロパティを持たないので、ランタイムエラーになります。
ちなみに、strict: true
(noImplicitAny: true
)になっている場合は下記のようにコンパイルエラーになります。
src/index.ts:2:22 - error TS7016: Could not find a declaration file for module './piyo'. 'src/piyo.js' implicitly has an 'any' type.
2 import { piyo } from "./piyo";
~~~~~~~~
Found 1 error.
こういう時に、型定義(.d.ts
)ファイルを同じディレクトリに作ることで、piyo.js
を型付きでimport
できるようになります。
// src/piyo.d.ts
declare const piyo = 123;
export { piyo };
この状態でコンパイルすることで、出て欲しかった「123
に trim
は無いよ」というエラーでコンパイルが止まります。
src/index.ts:5:18 - error TS2339: Property 'trim' does not exist on type '123'.
5 console.log(piyo.trim());
~~~~
Found 1 error.