在 TypeScript 中正确键入调用另一个生成器函数的生成器函数

Properly typing a generator function that calls another generator function in TypeScript

我有一个效用函数,它是一个生成器,如下所示:

function* myGenerator(): Generator<Foo, void> {
  ... // yield Foos
}

现在我想把这个效用函数包装在一个 class 中,像这样:

class MyWrapper {
  *generator(): Generator<Foo, void> {
    // call utils.myGenerator();
  }
}

问题是:如果我输入 MyWrapper.generator() 作为带有 * 符号的生成器,我不能简单地将它实现为 return utils.myGenerator(),因为生成器函数 returns无效,我会得到一个Type Generator<Foo, void> is not assignable to void错误。

我可以从 MyWrapper.generator() 中删除 *,让 return 类型为 Generator<Foo, void>,并且 return utils.myGenerator():

class MyWrapper {
  generator(): Generator<Foo, void> {
    return utils.myGenerator();
  }
}

... 但是丢失 * 会使调用者不太清楚这是一个生成器函数(当然,return 类型应该放弃它,但仍然)。

我还可以遍历“内部”生成器并从中生成所有内容:

class MyWrapper {
  *generator(): Generator<Foo, void> {
    for (const x of utils.myGenerator()) {
      yield x;
    }
  }
}

...但是这个额外的屈服层看起来很傻。

我是否缺少一种明显的方法来让一个生成器函数包装另一个生成器函数并仍然保持 * 表示法,例如“yield everything from”语法?

您可以使用 yield* 生成另一个生成器的所有元素

type Foo = string
function* myGenerator(): Generator<Foo, void> {
    yield "A";
    yield "B";
}


class MyWrapper {
  *generator(): Generator<Foo, void> {
    yield* myGenerator();
  }
}

console.log([...new MyWrapper().generator()]) // ["A", "B"] 

Playground Link