在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中工作的外部模块的正确方法是:
- 使用
--module umd
标志,然后在浏览器中使用AMD加载程序加载模块 - 使用
--module commonjs
标志,然后使用捆绑软件,如webpack或browserify
换句话说,当你开始编写模块化代码时,盲目地将<script>
标签添加到HTML文件不再是将代码加载到浏览器的正确方法。 正如你不应该在Node.js中触及全局作用域一样,你也不应该在浏览器中触及全局作用域。 你可以使用if (typeof window !== 'undefined') (<any>window).global = yourObject;
来破解它if (typeof window !== 'undefined') (<any>window).global = yourObject;
,但是严重的是, 千万不要这样做,这是错误的,它会打破 。
至于从外部模块向全局范围公开接口,没有办法做到这一点,因为你将不得不 从TypeScript 1.8开始,可以使用import
外部模块来获取其接口的引用,在这一点上,你已经创build了另一个外部模块。 declare global
来从模块内部增加全局types。