2016-02-09 79 views
1

我在TypeScript https://www.npmjs.com/package/html2commonmark中創作了一個npm模塊。該模塊可用於nodejs(使用require)和瀏覽器(在瀏覽器中加載node_modules/html2commonmark/dist/client/bundle.js)。在TypeScript中使用外部模塊聲明全局變量

爲了在使用"moduleResolution": "node"時獲得輸入信息,我最近添加了* .d.ts文件。這很好,當安裝我的模塊時,它已準備好用於打字稿。因此:以下一段打字稿代碼正在編譯時沒有錯誤:

// After installing using npm install html2commonmark 
// using "moduleResolution": "node" 
import * as html2commonmark from 'html2commonmark'; 
let converter = new html2commonmark.JSDomConverter(); 

很漂亮!

現在我想在瀏覽器中運行我的模塊。如前所述,我需要在我的index.html頁面上添加一個腳本標記到node_modules/html2commonmark/dist/client/bundle.js。之後,html2commonmark全局變量應該可用。問題是:我如何讓打字稿編譯知道全局變量在那裏?下面的TS碼片不會編譯:

let converter = new html2commonmark.BrowserConverter(); 
// error TS2304: Cannot find name 'html2commonmark'. 

即使我添加了一個global.d.ts文件,我似乎不能夠既導入我的外部模塊,並聲明我的全局變量:

// Something like this does not work :(
import * as b from 'html2commonmark'; 
declare var html2commonmark: typeof b; 

我明白這是爲什麼。通過使用import關鍵字,我的ts文件被轉換爲外部模塊,因此需要導入。然而我覺得我的場景是普遍的。也就是說:一個npm模塊,它包含一個npm組件和用於瀏覽器的bundle,它將這個功能公開爲一個全局變量。

是否有任何方法來使用我的外部模塊中的定義聲明全局變量?我不想重寫我的api作爲(DefinitelyTyped風格)命名空間,而我只是在TS中編寫我的整個源代碼...

回答

2

正確的方法來編寫一個外部模塊,在瀏覽器和Node.js的是:

  1. 使用--module umd標誌,然後使用AMD裝載機在瀏覽器中加載模塊
  2. 使用--module commonjs標誌,然後用捆綁喜歡的WebPack或browserify

換句話說,當你st藝術書寫模塊化代碼,盲目地將<script>標記添加到HTML文件不再是將代碼加載到瀏覽器的正確方法。正如你不應該觸及Node.js中的全局範圍一樣,你也不應該在瀏覽器中觸及全局範圍。你可以用if (typeof window !== 'undefined') (<any>window).global = yourObject;來破解它,但是嚴重的是,不會這樣做,它是錯誤的,它會破壞

至於將接口從外部模塊暴露給全局範圍,沒有辦法做到這一點,因爲你必須import外部模塊來獲取其接口的引用,在這一點上你已經創建另一個外部模塊。從TypeScript 1.8起,您可以使用declare global從模塊內部擴充全局類型。

+0

感謝您的回覆!爲了生成bundle.js我使用的是webpack。當然,我也可以強制(打字稿)消費者爲瀏覽器編寫使用webpack/browserify。我只是想知道是否有更好的方法。我覺得應該有可能。 使用'(窗口)。全球= yourObject'是不需要的,因爲對象已經可以在全球範圍內(至少:包括你的頁面上的bundje.js時)。我只是想找一種方法讓它看起來像打字稿。 – nicojs

+0

在這種情況下,答案是一個更簡單的「否」:)你可以通過'declare module「foo」{export = SomeGlobal;}來將全局接口暴露給手寫的d.ts文件中的已命名模塊。 '',但是沒有辦法走向另一個方向。 –

+0

這太糟糕了。如果您更新與短版的答案 – nicojs