网站搜索

在 TypeScript 的 .d.ts 文件中,`export as namespace`是什么意思?


我一直在阅读 DefinitelyTyped 上的一些声明文件,并且经常遇到像这样的文件:

declare function domready(callback: () => any) : void;

export = domready;
export as namespace domready;

我理解前两行——声明一个函数并将该函数作为模块对象导出。但是最后一行是什么?我在声明文件中需要这个吗?它是做什么的?

答案#1

这是一个 UMD 模块声明。

如果你还不熟悉,UMD 是一种创建模式,它允许同一个 JavaScript 库根据环境的不同,被用作 全局变量(可以在任何地方访问的变量)或作为 模块(在运行时专门加载的模块)。

许多库是用 UMD 模式编写的。例如,你可以写

moment.parse("12-31-2017")

在浏览器中,但在 node.js 中这样写代码:

const m = require("moment");
m.parse("12-31-2017")

当你写一个 export 声明,比如 export function parse 时,TypeScript 知道你是在描述一个像第二段代码那样的 模块。但如果你为其编写 .d.ts 文件的库也创建了一个全局变量,你可以使用 UMD 模块声明语法来描述该全局变量:

export as namespace the_global_identifier;

一些 UMD 库会始终创建全局变量,而其他库必须在存在模块系统的环境中被导入。通常,库并没有明确记录它们使用的是哪种行为,这意味着声明文件的作者并不真正知道会出现哪种情况,这也意味着 TypeScript 是保守的,只有当引用它的文件不是模块时,才会允许访问全局标识符。

如果你正在编写声明文件,并且不确定该库是否是 UMD,请检查是否有类似这样的模式:

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ?     factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (factory((global.mymodule = global.mymodule || {})));
}(this, function (exports) { 'use strict';
    function myFunction() {
        console.log('hello world');
    }
}));

这是典型的 UMD 气味:大量使用 typeof 检查“exports”、“module”和“define”,然后赋值给传递给一个大函数体的“exports”参数。如果你在库代码中没有看到这些,它几乎肯定不是 UMD 模块,你不应该写 export as namespace 声明。

相关文章