在TypeScript中使用外部模块声明全局variables

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

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

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

美丽!

现在我想在浏览器中运行我的模块。 如前所述,我需要添加一个脚本标记到node_modules/html2commonmark/dist/client/bundle.js到我的index.html页面。 之后,html2commonmark全局variables应该可用。 问题是:我如何让打字稿编译知道全局variables在那里? 以下的TS代码将不会编译:

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

即使我添加一个global.d.ts文件,我似乎无法同时导入我的外部模块,并声明我的全局variables:

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

我明白这是为什么 通过使用导入关键字,我的ts文件被转换为外部模块,因此需要导入。 然而,我觉得我的情况是一个普遍的情况。 也就是说:一个npm模块,包含一个npm组件和浏览器的包,这个包把function公开为一个全局variables。

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

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

  1. 使用--module umd标志,然后在浏览器中使用AMD加载程序加载模块
  2. 使用--module commonjs标志,然后使用捆绑软件,如webpack或browserify

换句话说,当你开始编写模块化代码时,盲目地将<script>标签添加到HTML文件不再是将代码加载到浏览器的正确方法。 正如你不应该在Node.js中触及全局作用域一样,你也不应该在浏览器中触及全局作用域。 你可以使用if (typeof window !== 'undefined') (<any>window).global = yourObject;来破解它if (typeof window !== 'undefined') (<any>window).global = yourObject; ,但是严重的是, 千万不要这样做,这是错误的,它会打破

至于从外部模块向全局范围公开接口,没有办法做到这一点,因为你将不得不import外部模块来获取其接口的引用,在这一点上,你已经创build了另一个外部模块。 从TypeScript 1.8开始,可以使用declare global来从模块内部增加全局types。