2012-11-18 100 views
13

TypeScripts以「聲明式」方式抽取模塊導入/導出。TypeScript - 條件模塊導入/導出

但是如果我想根據某些運行時間計算條件導入或導出某些內容呢?

最常見的用例是在Node.js和Windows Script Host等平臺之間共享代碼。

TypeScript自帶的io.ts在TSC編譯器中對輸入/輸出進行了抽象,手動繞過了內置TypeScript自己的模塊語法。這是唯一的方法嗎?

P.S.如果語句是TypeScript只允許在頂層的導入語句,只需堅持導入fs =模塊(「fs」)的問題。這意味着在WSH 要求(「fs」)將被執行並明顯失敗,因爲要求是未定義的。

回答

8

我同意的事實,他們只能有頂級的範圍是次優的最好的。除了你提到的問題外,這也意味着軟件的初始加載時間較慢。例如,在nodejs中,我現在有時會在函數中加載模塊,如果該函數很少使用。所以我的應用程序啓動速度更快,因爲它尚未加載該模塊。

當然,你可以使用要求或AMD直接,但比你會錯過一些打字好處。

我覺得然而,真正的問題在於這樣一個事實:和諧/ ES6定義的模塊是頂層和TS似乎是下面這一建議。所以不確定沒有來自標準組織的TS團隊可以做多少事情。

0

有在打字稿動態進口的機制,雖然有所不同實施基於模塊的那種。

下面的例子(對於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. 導入文件將期望值被定義。因此,您必須確保導入文件實際上需要模塊(如果您正在處理僅在測試期間運行的文件,那麼這很好),或者您必須爲其實際上未導出的情況定義替代值。

儘管如此,它仍然適合我的目的,希望它也適用於您。這對單元測試私有方法特別有用。