2012-11-18 18 views
13

TypeScriptsは、モジュールのインポート/エクスポートを「宣言的」なやり方で抽象化します。TypeScript - 条件付きモジュールのインポート/エクスポート

しかし、実行時の計算条件に基づいて何かをインポートまたはエクスポートしたいのですが?

最も一般的な使用例は、Node.jsやWindows Script Hostなどのプラットフォーム間でコードを共有する場合です。

TypeScriptの独自のio.tsは、TSCコンパイラの入出力を抽象化し、組み込みのTypeScriptの独自のモジュール構文を手動でハックします。それが唯一の方法ですか?

P.S. をインポートした場合の問題ステートメントの場合、最上位レベルのインポートステートメントのみが許可されているという文脈では、に入力してください。これは、が要求する( "fs")が実行され、明らかに失敗することを意味します。が必要です。は未定義です。

答えて

8

は、私は、彼らが唯一のトップレベルのスコープを持つことができるという事実は、最高の状態で最適ではないことに同意します。あなたが述べた問題の他に、ソフトウェアの初期読み込み時間が遅くなることも意味します。例えばnodejsの中で、関数をあまり使用しない場合、モジュールを関数にロードすることがあります。だから私のアプリケーションは、まだモジュールをロードしていないので、起動が早くなります。

もちろん、requireやAMDを直接使用することもできますが、タイピングのメリットのいくつかを見逃してしまいます。

しかし、本当の問題は、ハーモニー/ es6で定義されたモジュールがトップレベルとTSであることがその提案に従っているように思えるということです。 TSチームが標準化団体から派生しなければ、どれくらいのことができるか分かりません。

0

実装はモジュールの種類によって異なりますが、TypeScriptでは動的インポートの仕組みがあります。

条件付きモジュールをロードする(AMD用)以下の例:

declare function require(moduleNames: string[], onLoad: (...args: any[]) => void): void; 

import * as ModuleAlias from './mod'; 

const someCondition = true; 

if (someCondition) { 
    require(["./mod"], (module: typeof ModuleAlias) => { 
     console.log(module.go()); 
    }); 
} 

ファイルの先頭にimportステートメントは、不活性であり、モジュールの実際のローディング条件if (someCondition)ない限り起こりません本当です。

someConditionを変更し、ネットワークタブへの影響を確認するか、生成されたコードを見ることができます。"./mod"defineコールには表示されません。非動的なものでは、それはそうです。ダイナミックロードせずに、動的ロード

define(["require", "exports"], function (require, exports) { 
    "use strict"; 
    Object.defineProperty(exports, "__esModule", { value: true }); 
    const someCondition = true; 
    if (someCondition) { 
     require(["./mod"], (module) => { 
      console.log(module.go()); 
     }); 
    } 
}); 

define(["require", "exports", "./mod"], function (require, exports, ModuleAlias) { 
    "use strict"; 
    Object.defineProperty(exports, "__esModule", { value: true }); 
    const someCondition = true; 
    if (someCondition) { 
     console.log(ModuleAlias.go()); 
    } 
}); 
5

これは、特に単体テスト用の条件付きインポート/エクスポートを使用している場合、これは非常に控えめですが非常に効果的なソリューションです。

エクスポートは常に発行されますが、内容は実行時の値によって異なります。例えば。:消費したファイルで次に

// outputModule.ts 
export const priv = (process.env.BUILD_MODE === 'test') 
    ? { hydrateRecords, fillBlanks, extractHeaders } 
    : null 

は、インポートされた値が存在することを確認し、輸出をインポートし、それがない場合は、変数のセットに、あなたがそうでなければ、スタンドアローンインポートしたいすべての値を割り当てます。

// importingModule.spec.ts 
import { priv } from './outputModule'; 

const { hydrateRecords, fillBlanks, extractHeaders } = priv as any; 
// these will exist if environment var BUILD_MODE==='test' 

制限事項:

  1. あなたは悲しそうに「任意の」は、コンパイラを幸せにするために、インポートを設定する必要があります。
  2. 特定のインポートが定義されているかどうかを確認する必要があります(しかし、それは地域に付属しています)。
  3. インポートファイルでは、値の定義が必要です。したがって、ファイルのインポートに実際にモジュールが必要であることを確認する必要があります(たとえば、テスト中にのみファイルを処理する場合は問題ありません)。あるいは、実際にエクスポートされない場合は代替値を定義する必要があります。

まだ、それは私の目的のために私にとって本当にうまくいきました。うまくいけばそれもあなたのために働きます。プライベートメソッドの単体テストに特に便利です。