如何记录 javascript 高阶函数?

How to document javascript higher order function?

我有以下用于包装构造函数的高阶函数:

/**
 * Wrapper for calling constructor with given parameters
 *
 * @param {Class} Cls
 * @returns {function} Wrapper on constructor which creates an instance of given Class
 */
function constructorWrapper(Cls) {
    return (...args) => new Cls(...args);
}

所以如果我有 class MyClass,我可以执行以下操作:

exports.MyClass = MyClass;
exports.myClass = constructorWrapper(MyClass);

现在class导入后可以通过以下两种方式实例化:

const instance1 = new MyClass(param1, param2);
const instance2 = myClass(param1, param2);

在 vscode 中,instance1 将具有智能感知支持,但 instance2 不会。如何记录 function/export 以便将使用包装器创建的对象识别为 class 的实例?

您可以通过强制 myClass:

的类型使 IntelliSense 可用
/** @type {function(T1, T2): MyClass} */
exports.myClass = constructorWrapper(MyClass);

但是,如果您想注释 constructorWrapper 本身,那么从 VSCode 1.11.1(使用 TypeScript 2.2)开始,这是不可能的。而 JSDoc supports generics:

/**
 * Wrapper for calling constructor with given parameters
 *
 * @param {function(new:T, ...*)} Cls The class constructor.
 * @returns {function(...*): T} Wrapper of the class constructor
 * @template T
 */
function constructorWrapper(Cls) {
    return (...args) => new Cls(...args);
}

并且推断的类型确实是正确的:

不知何故,两个 "T" 断开连接,使得 myClass = constructorWrapper(MyClass) 采用类型签名 (...arg0: any[]) => T。什么T?好吧,我们不知道,将其视为 any 而不是 IntelliSense。

VSCode 的 JSDoc-based IntelliSense 基于 TypeScript,I think this is a bug in TypeScript's handling of @template 从 2.2 开始。

如果你不局限于 ES6-only-development,我建议你完全用 TypeScript 重写它。然后您将获得预期的 IntelliSense,以及类型安全和许多其他好处。

请注意,由于 TypeScript 2.2 does not support variadic generics yet 不能完美转发参数,因此 myClass 的输入不能是 type-checked。这意味着您仍然需要手动注释 myClass 的类型以获得完美的信息。