当前位置: 首页 > 知识库问答 >
问题:

如何使用JSDoc为递归闭包编写显式返回类型注释

辛承志
2023-03-14

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

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

/**
 * @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());

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

共有1个答案

羊昊苍
2023-03-14

将函数定义与返回分开,可以对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();
  };
};
 类似资料:
  • 为了概括这个问题,我借用了Zelenski CS课堂讲义中的材料。而且,这与我的具体问题有关,因为几年前我从另一位讲师那里学习了C语言的这种方法。讲义在这里。我对C的理解很低,因为我偶尔使用它。基本上,我需要编写一个程序的几次,我回到课堂材料,找到类似的东西,然后从那里开始。 在本例(第4页)中,Julie正在字符串函数中使用递归算法查找单词。为了减少递归调用的数量,她添加了一个决策点。 为了增加

  • 我正在编写一种没有键入函数的语言。这意味着我需要推断函数调用的返回类型,以便进行类型检查。然而,当有人编写递归函数时,类型检查器进入无限递归,试图推断函数体中函数调用的类型。 类型检查器执行如下操作: 推断函数调用实际参数的类型 然后,步骤4尝试推断函数体内部函数调用的类型,该函数体再次调用相同类型的检查器函数,导致无限递归。 递归函数的一个例子给了我这个问题: 我如何在不进入无限递归循环的情况下

  • 所以我明白了如何使用一个递归方法,它有一些其他的返回类型,而不是作废。通常我会在同一个方法中再次调用相同的方法(在递归的情况下),同时在调用中递减或增加一些值以达到基本情况。然后在某个时候达到基本情况,问题就解决了,所以它开始返回每个调用的值。沿着这些路线。 但是 如果该方法的返回类型为void,那么您不能调用该方法,因为它不会/不能返回任何内容,该怎么办?我试着倒着写一个句子,我已经用for循环

  • 问题内容: 在Swift中,如果闭包仅包含单个语句,它将自动返回从该单个语句返回的值。 并非在所有情况下都感觉很自然。让我们看一个例子: 如您所见,即使闭包只应调用一个简单函数,它也会尝试自动返回其返回值,该返回值的类型为,与返回类型不匹配。 我可以通过实现闭包主体来避免这种情况: 感觉非常奇怪。 有没有更好的方法可以做到这一点,或者这仅仅是我必须忍受的东西? 问题答案: 发生这种情况的原因是单行

  • 我正在编写一个简单的“proc”来计算阶乘。我想了解为什么我的函数没有返回语句就无法工作。 根据TCL文档,没有显式“return”定义的函数返回其主体中最后执行的命令的值。 当“返回”被删除时,我收到以下错误消息: 我希望如果没有显式的“return”,函数也应该返回24。

  • 我试图在Java中创建一个方法,它打印fib序列,直到传递给该方法的数字。我的问题是,我需要使用int返回类型来返回序列,而我不能使用递归。