网站搜索

typescript - 如何展开异步或同步生成器


我想解包一个异步生成器或同步生成器,并获取它的内部返回类型。

也就是说,我在寻找一个用于 Promise 的 Awaited 的等效物。

对于我曾经做出的承诺:

async function foo() {
}

let returnValue: Awaited<ReturnType<typeof foo>>;

对于发电机,我正在寻找:

async function* foo() {
}

function* bar() {
}

let returnValue: ???<ReturnType<typeof foo | typeof bar>>;

答案#1

es2015.iterable 包含你可以用来推断 yield 值的 Generator 类型:

function* foo() {
  yield 1;
  yield 2;
}

function* bar() {
  yield 3;
  yield 4;
}

type GeneratorValue<G extends (...arg: any[]) => any> = ReturnType<G> extends Generator<infer X> ? X : never;

type fooG = GeneratorValue<typeof foo | typeof bar> // 1 | 2 | 3 | 4

操场

使用这个为异步生成器打字不起作用,我也不能轻松地从现有接口扩展 AsyncGenerator 类型,但似乎某种程度上是可能的。

答案#2

你可以像实现 ReturnType 那样实现你的工具类型,只不过不是推断整个返回类型,而是推断 AsyncGenerator 和 Generator 泛型类型的类型参数(因为当你在 TypeScript 中查看生成器/异步生成器函数的声明时,它们返回的就是这些类型):

type GenYieldType<T extends (...args: any) => Generator<any, any, any>> =
  T extends (...args: any) => Generator<infer R, any, any> ? R : never;

type AsyncGenYieldType<T extends (...args: any) => AsyncGenerator<any, any, any>> =
  T extends (...args: any) => AsyncGenerator<infer R, any, any> ? R : never

让我们来试试:

async function* foo() { yield "a"; yield "b"; }
type FooYield = AsyncGenYieldType<typeof foo>
//   ^? type FooYield = "a" | "b"
    
function* bar() { yield "c"; yield "d"; }
type BarYield = GenYieldType<typeof bar>
//   ^? type BarYield = "c" | "d"

看起来不错。

代码的 Playground 链接