有没有办法获得生成器函数的返回类型?

Thu*_*San 7 iterator typescript

我想获取生成器函数的返回类型。
例如

function* test(){
  yield 'a';
  yield 123;

  return true;
}

// what I'm trying to get
type A = GetGeneratorReturn<test>; // -> A has type boolean
Run Code Online (Sandbox Code Playgroud)

我目前处于什么状态。

type B = ReturnType<ReturnType<typeof test>['next']>['value'];
// B has type `true | "a" | 123`
Run Code Online (Sandbox Code Playgroud)

(我想如果我得到 Union 类型 B 的第一项,我就可以获得返回类型)

jca*_*alz 7

有一个开放的问题讨论了这个问题,但它已经很老了,而且看起来没有人关注它,因为其他一些问题已经得到解决。我最近到处都看到有人提到它。最相关的问题似乎是这个。如果这对您很重要,您可能需要前往 GitHub 并给出这些问题的一些信息。

目前看来,TypeScript 中的生成器类型只能让您访问yield类型和return类型的无差别联合。不幸的是,您不能依赖联合类型的排序。这是编译器的实现细节;由于X | Y相当于Y | X,编译器可以随意将其中之一更改为另一个。有时确实如此:

function* test() {
  yield 'a';
  yield 123;
  return true;
} // function test(): IterableIterator<true | "a" | 123>

function* oops() {
  yield true;
  yield 123;
  return 'a'
} // function oops(): IterableIterator<true | "a" | 123>
Run Code Online (Sandbox Code Playgroud)

的返回类型与的返回类型oops()完全相同。这意味着您提取联合的第一个/最后一个元素的想法是不可能的。test()

可能有一种解决方法会有所帮助,特别是如果您可以弄乱生成器定义并且不介意一些浮动的幻像类型:

type Returnable<T> = { __returnedType?: T } & T
const ret = <T>(t: T) => t as Returnable<T>;
type GeneratorReturn<T extends (...args: any) => IterableIterator<any>> =
  ReturnType<T> extends IterableIterator<infer I> ?
  NonNullable<Extract<I, Returnable<unknown>>['__returnedType']> : never

function* test() {
  yield 'a';
  yield 123;
  return ret(true); // only use ret() here
} 

function* oops() {
  yield true;
  yield 123;
  return ret('a'); // only use ret() here
} 

type TestRet = GeneratorReturn<typeof test>; // true
type OopsRet = GeneratorReturn<typeof oops>; // "a"
Run Code Online (Sandbox Code Playgroud)

就其本身而言,这很有效,但可能不是您想要追求的目标。哦,抱歉,我在这里找不到更好的答案。祝你好运!


Ore*_*lus 5

你现在可以这样做:

type GeneratorReturnType<T extends Generator> = T extends Generator<any, infer R, any> ? R: never;
type TestType =  GeneratorReturnType<ReturnType<typeof test>>; // bool
Run Code Online (Sandbox Code Playgroud)

操场