created: 2023-02-09T01:58:12.820Z
cannot be compiled under --isolatedModules because it is considered a global script file
isolatedModules
フラグでこんなエラーに遭遇した。
function fn() {}
'index.ts' cannot be compiled under '--isolatedModules' because it is considered a global script file. Add an import, export, or an empty 'export {}' statement to make it a module.
よくわからなかったのでドキュメントを調べた。
概要
- babelなどのソフトウェアはTypeScriptファイルをJavaScriptにトランスパイルする機能をもっているが、あくまで別なソフトウェアなので、TypeScript型システムの仕様を完全に遵守したトランスパイルができない可能性がある
- それはbabelがオペレーションする対象が一度に1ファイルという制約をもっていることにもよるらしい
- この制約は
ts.transpileModule
を使っている他のモジュールにも同様である
- 完璧なトランスパイルができない以上、ランタイムでクラッシュしてしまう可能性がある
const enum
やnamespace
などの独自機能を使用しているととくに怪しいらしい
isolatedModules
フラグは、(babelなどが)きちんとトランスパイルできない可能性があるコードを見つけると警告を出してくれるためのフラグである- トランスパイル結果は変わらない。あくまでtscのチェック機能が厳しくなるというフラグである
Non-Module Files
「きちんとトランスパイルできない可能性がある」とのことだが、今回は Non-Module Files
ということでこの警告に引っ掛かっていた。
If isolatedModules is set, all implementation files must be modules (which means it has some form of import/export). An error occurs if any file isn’t a module:
TypeScript では import/export の宣言がないファイルはスクリプトモードだとみなされるのだが、このモードだと完璧なトランスパイルができない可能性があるらしい。理由はピンとこない。しかしそれで警告がでているとのことだった。
ちなみにエラーを消すだけなら簡単で、以下の1行を追加すれば消える。
export {}
ChatGPT
なぜスクリプトモードだとトランスパイルに失敗する可能性があるのかをChatGPTに尋ねてみた。
僕
TypeScript において、tsconfig.json の設定である isolatedModules フラグをオンにしたところ、 Non-Module Files はトランスパイルが失敗する可能性があるとして警告されました。なぜ Non-Module Files だとトランスパイルが失敗する可能性があるのでしょうか?
AI
"isolatedModules" フラグを "true" に設定すると、TypeScript コンパイラはモジュールシステムを使用しないファイル (Non-Module Files) に対して警告を生成します。これは、Non-Module Files は完全な TypeScript モジュールシステムをサポートしていないため、外部からアクセスできない内部の変数や関数を含んでいる場合があり、それらの変数や関数を参照することができないというトランスパイルのエラーが発生する可能性があるからです。
モジュールシステムを使用すると、外部からのアクセスを制御することができます。しかし、Non-Module Files にはこの機能がないため、外部からアクセスできる変数や関数を宣言する必要があります。
...
スクリプトモードってそうなの?
Non-Module Files は完全な TypeScript モジュールシステムをサポートしていない
tsc だと解決できる変数や関数の参照が、babel だと解決ず、ランタイムでそれらが undefined
になるかもしれないということなのかな。
外部からアクセスできない内部の変数や関数を含んでいる場合があり、それらの変数や関数を参照することができないというトランスパイルのエラーが発生する可能性があるからです。
とりあえず export {}
と書けばモジュールモードになってくれるのでそのような憂いもなくなるという理屈だったということで、ちゃんとした理解には至らなかったが、いったん納得することにした。