首页 > 解决方案 > 如何使用 JSDoc 为递归闭包编写显式返回类型注释

问题描述

我在一个项目中有一个相当复杂的用例,它使用 vanilla JS 并使用tscJSDoc 注释中编写的类型注释检查类型。我有一个返回函数的函数,返回的函数可能会递归调用自身,同时还会重新分配一些闭包变量。

这是一个愚蠢的例子,它明白了这一点,并会抛出同样的错误:

/**
 * @returns {function(): number}
 */
function circular() {
  let num = Math.random();

  return function tryAgain() {
    if (num < 0.5) {
      return num;
    }

    num = Math.random();
    return tryAgain();
  };
}

因此,如果我使用以下代码对此代码运行类型检查tsc

tsc --allowJs --checkJs --noEmit --strict --target ES2017 *.js

我收到以下错误:

error TS7023: 'tryAgain' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.

首先,这个错误似乎非常错误。我显然有一个明确的返回类型注释,这是为使用适当的 TypeScript 而不是 JSDoc的类似循环引用提出的解决方案。

但是我很高兴有任何解决方法可以在没有大量重构的情况下进行编译,从而消除闭包和/或递归。我已经尝试了许多可能的解决方法,但都没有奏效。

用注释包装返回函数:

  return /** @type {function(): number} */ (function tryAgain() {
    . . .
  });

用注释包装递归调用:

    return /** @type {number} */ (tryAgain());

用强制包装递归调用:

    return Number(tryAgain());

在这一点上,我完全不知道如何正确地注释它,或者至少如何让该死的东西编译。

标签: typescriptrecursionclosuresjsdoc

解决方案


将函数定义与return分开可以让您进行注释tryAgain,从而消除错误:

/**
 * @returns {function(): number}
 */
function circular() {
  let num = Math.random();

  /**
   * @returns {number}
   */
  function tryAgain() {
    if (num < 0.5) {
      return num;
    }

    num = Math.random();
    return tryAgain();
  }

  return tryAgain;
}

内联也可以:

/**
 * @returns {function(): number}
 */
function circular() {
  let num = Math.random();

  return /** @returns {number} */ function tryAgain() {
    if (num < 0.5) {
      return num;
    }

    num = Math.random();
    return tryAgain();
  };
};

推荐阅读