如何记录javascript高阶函数?

Suh*_*s K 5 javascript documentation higher-order-functions jsdoc3 visual-studio-code

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

/**
 * 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);
}
Run Code Online (Sandbox Code Playgroud)

因此,如果我有一个 class MyClass,我可以执行以下操作:

exports.MyClass = MyClass;
exports.myClass = constructorWrapper(MyClass);
Run Code Online (Sandbox Code Playgroud)

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

const instance1 = new MyClass(param1, param2);
const instance2 = myClass(param1, param2);
Run Code Online (Sandbox Code Playgroud)

在 vscode 中,instance1会有智能感知支持,但instance2不会。如何记录函数/导出以便使用包装器创建的对象被识别为类的实例?

ken*_*ytm 4

您可以通过强制以下类型来使 IntelliSense 可用myClass

/** @type {function(T1, T2): MyClass} */
exports.myClass = constructorWrapper(MyClass);
Run Code Online (Sandbox Code Playgroud)

但是,如果您希望constructorWrapper对其自身进行注释,则从 VSCode 1.11.1(使用 TypeScript 2.2)开始这是不可能的。虽然JSDoc 支持泛型

/**
 * 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);
}
Run Code Online (Sandbox Code Playgroud)

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

<code>function constructorWrapper<T>(Cls: new (...arg1: any[]) => T): (...arg0: any[]) => T</code>

不知何故,两个“T”变得断开,使得myClass = constructorWrapper(MyClass)采用类型签名(...arg0: any[]) => T。什么T?好吧,我们不知道,那就把它当作any没有 IntelliSense 吧。

<code>myClass: (...arg0: 任意[]) => T</code>

VSCode 的基于 JSDoc 的 IntelliSense 是基于 TypeScript 的,我认为这是 TypeScript@template从 2.2 开始的处理中的一个错误。

如果您不限于仅限 ES6 开发,我建议您完全用 TypeScript 重写它。然后您将获得预期的 IntelliSense、类型安全和许多其他好处。

请注意,由于TypeScript 2.2 不支持可变泛型,但参数无法完美转发,因此无法对输入myClass进行类型检查。这意味着您仍然需要手动注释 的类型myClass才能获得完美的信息。