使用TypeScript中的外部模块声明全局变量

时间:2016-02-09 14:12:08

标签: javascript node.js typescript typescript1.7

我在TypeScript https://www.npmjs.com/package/html2commonmark中创作了一个npm模块。该模块可用于nodejs(使用require)和浏览器(通过在浏览器中加载node_modules/html2commonmark/dist/client/bundle.js)。

我最近添加了* .d.ts文件,以便在使用"moduleResolution": "node"时获取输入信息。这很好用,在安装我的模块时,它已准备好用于打字稿。因此:以下的打字稿代码正在编译而没有错误:

// 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组件和浏览器包,它将功能公开为全局变量。

有没有办法使用我的外部模块中的定义来声明全局变量?我不想将我的api重写为(DefinitelyTyped风格)命名空间,而我只是在TS中编写完整的源代码...

1 个答案:

答案 0 :(得分:2)

编写可在浏览器和Node.js中运行的外部模块的正确方法是:

  1. 使用--module umd标志,然后在浏览器中使用AMD加载程序加载模块
  2. 使用--module commonjs标志,然后使用像webpack或browserify这样的捆绑包
  3. 换句话说,当您开始编写模块化代码时,盲目地将<script>标记添加到HTML文件不再是将该代码加载到浏览器中的正确方法。正如您不应该触及Node.js中的全局范围一样,您也不应该在浏览器中触及全局范围。你可以用if (typeof window !== 'undefined') (<any>window).global = yourObject;破解它,但严重的是,不要这样做,这是错误的,它会破坏

    就将外部模块中的接口暴露给全局作用域而言,没有办法做到这一点,因为您必须import外部模块才能获得对其接口的引用,您创建了另一个外部模块。从TypeScript 1.8开始,您可以使用declare global从模块内部扩充全局类型。

相关问题