Javascriptの条件つきコンパイル

TypescriptやJavascriptの言語仕様には条件つきコンパイルを含むマクロがありませんが、esbuildにはその機能があります。

if(DEBUG) {
  console.debug(`${some_variable}`);
}

このようなコードブロックのうちDEBUGはそのままではundefinedです。esmoduleはファイルスコープであり、このDEBUGは解決できません。

esbuildの define機能は、コンパイル時に変数の値を指定できます。
--define:DEBUG=falseによりif(false)に置き換えられた場合、minifyプロセスでこのブロックは除去されます。

なお、この意図でDeno.env.get("DEBUG")などの変数を用いても期待どおりのコンパイル結果にはなりません。コードに変数がそのまま残り、実行時にチェックする挙動となります。
また、DEBUGを別のファイルで定義してimportしたコードもブロックは残ります。

条件つきコンパイルを用いると、デバッグメッセージの出力のほか、変数チェックも実装できます。

if(DEBUG) {
  if (!not_nullable_doubtful) throw new Error("not_nullable_doubtful finally got null");
}

Typescriptは型を定義した部分のみチェックできますが、この実行時チェックであれば型を定義する必要がなく、外部ライブラリを経由した値もチェックできます。

テストでは実装の詳細をチェックすべきではないと考えられていますが、実際には変数の状態こそが決め手になることが多くあり、関数内でローカルな変数をインスペクトする方法は変更に弱いというネックもありません。

ただしdefineを導入すると、そのコードはTypescript/Javascriptではなくなり、esbuildでトランスパイルしないと実行できなくなる点をあらかじめ理解しておく必要があります。

中馬崇尋
Chuma Takahiro