IntelliSense/JSDoc @param = @return, a.k.a。我如何记录包装函数?

IntelliSense/JSDoc @param = @return, a.k.a. how do I document wrapper functions?

我有一个函数接受另一个函数作为参数,对该函数参数做一些事情,然后returns相同的函数参数(或至少 returns 一个具有完全相同签名的函数)

/**
 * The param and return should be the same (as far as JSDoc is concerned)!
 * @param {Function} fnToWrap
 * @returns {fnToWrap}
 */
function wrapperFunction(fnToWrap) {
    // Does something...
    return fnToWrap;
}

但是,从我在下面的评论中可以看出...

/**
 * IntelliSense detects this...
 * @param paramA 
 * @returns 
 */
var arbitraryFn = function(paramA) {
    return paramA * 2;
}


// But NOT this!!!
var wrappedArbitraryFn = wrapperFunction(arbitraryFn);

... IntelliSense 将在调用 arbitraryFn() 而不是 wrappedArbitraryFn().

时自动完成

有什么方法可以让 IntelliSense 动态地 自动完成我的包装函数,并使用与未包装函数相同的签名,即 没有 明确地重新记录每个新包装的函数?

不完全是我要找的东西,但在发布这个问题后我确实发现了这个还不错的方法:

/**
 * @type {arbitraryFn}
 */
var wrappedArbitraryFn = wrapperFunction(arbitraryFn);

这很有效并且不太乏味,但请注意以下几点:

  • 这需要预先定义原始函数。换句话说,我无法使它适用于在包装函数调用中声明的函数,例如这不适用于 var wrapped = wrapperFunction((a, b) => a + b)
  • 如果您在 Visual Studio 代码 中尝试使用“重命名符号”命令 (F2) 重命名函数,这将中断 除非 你用 @typedef 记录原始函数。每次放一个 @typedef 可能没问题,但我不知道该标签是否有任何副作用。此外,这是一个需要记住的额外步骤,如果您忘记了它,也不会产生 obvious/immediate 后果

所以我仍然非常愿意回答!

我再次讨论这个问题,因为我现在有一个(接近)完美的解决方案来处理我的用例。事实上,IntelliSense 比标准 JSDoc 的 TypeScript far 多。事实证明,您可以利用 @template 标记来解决上述问题,据我所知,我可以在 TypeScript 中完成的任何事情我也可以在 JavaScript 中完成智能感知:

新包装函数

/**
 * The param and return should be the same (as far as JSDoc is concerned)!
 * @template {Function} T
 * @param {T} fnToWrap
 * @returns {T}
 */
 function wrapperFunction(fnToWrap) {
    // Does something...
    return fnToWrap;
}

包装一个先前声明的函数

/**
 * IntelliSense detects this...
 * @param {Number} paramA 
 */
function previouslyDeclared(paramA) {
    return paramA * 2;
}

// And it also detects this!
var afterWrapping = wrapperFunction(previouslyDeclared);

包装内联函数

// And it also detects this!
var wrappedArbitraryFn = wrapperFunction(
    /**
     * IntelliSense detects this
     * @param {String} a 
     * @param {Number} b 
     * @param {Function} c 
     * @returns 
     */
    (a, b, c) => {
        return 22;
    }
);

对我来说唯一的缺点是内联有点难看,imo,但它有效。但是,请注意 这可能不是 true/vanilla JSDoc 的有效解决方案。如果您像我一样,并不真正了解 JSDoc,并且您真的只是来这里了解 IntelliSense,那么这个解决方案就很棒。