Do not infer yield* type from contextual TReturn (#58621)

This commit is contained in:
Ron Buckton 2024-05-29 18:05:00 -04:00 committed by GitHub
parent 2a9e4b8aa2
commit 718d79807c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 331 additions and 6 deletions

View File

@ -30915,9 +30915,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (!node.asteriskToken && contextualReturnType.flags & TypeFlags.Union) {
contextualReturnType = filterType(contextualReturnType, type => !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsyncGenerator));
}
return node.asteriskToken
? contextualReturnType
: getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, isAsyncGenerator);
if (node.asteriskToken) {
const iterationTypes = getIterationTypesOfGeneratorFunctionReturnType(contextualReturnType, isAsyncGenerator);
const yieldType = iterationTypes?.yieldType ?? silentNeverType;
const returnType = getContextualType(node, contextFlags) ?? silentNeverType;
const nextType = iterationTypes?.nextType ?? unknownType;
const generatorType = createGeneratorType(yieldType, returnType, nextType, /*isAsyncGenerator*/ false);
if (isAsyncGenerator) {
const asyncGeneratorType = createGeneratorType(yieldType, returnType, nextType, /*isAsyncGenerator*/ true);
return getUnionType([generatorType, asyncGeneratorType]);
}
return generatorType;
}
return getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, contextualReturnType, isAsyncGenerator);
}
}
@ -37829,7 +37839,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
if (isGenerator) {
return createGeneratorReturnType(
return createGeneratorType(
yieldType || neverType,
returnType || fallbackReturnType,
nextType || getContextualIterationType(IterationTypeKind.Next, func) || unknownType,
@ -37846,7 +37856,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}
function createGeneratorReturnType(yieldType: Type, returnType: Type, nextType: Type, isAsyncGenerator: boolean) {
function createGeneratorType(yieldType: Type, returnType: Type, nextType: Type, isAsyncGenerator: boolean) {
const resolver = isAsyncGenerator ? asyncIterationTypesResolver : syncIterationTypesResolver;
const globalGeneratorType = resolver.getGlobalGeneratorType(/*reportErrors*/ false);
yieldType = resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || unknownType;
@ -40648,7 +40658,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const generatorYieldType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, returnType, (functionFlags & FunctionFlags.Async) !== 0) || anyType;
const generatorReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, (functionFlags & FunctionFlags.Async) !== 0) || generatorYieldType;
const generatorNextType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Next, returnType, (functionFlags & FunctionFlags.Async) !== 0) || unknownType;
const generatorInstantiation = createGeneratorReturnType(generatorYieldType, generatorReturnType, generatorNextType, !!(functionFlags & FunctionFlags.Async));
const generatorInstantiation = createGeneratorType(generatorYieldType, generatorReturnType, generatorNextType, !!(functionFlags & FunctionFlags.Async));
return checkTypeAssignableTo(generatorInstantiation, returnType, errorNode);
}

View File

@ -0,0 +1,96 @@
//// [tests/cases/compiler/asyncYieldStarContextualType.ts] ////
=== asyncYieldStarContextualType.ts ===
// https://github.com/microsoft/TypeScript/issues/57903
interface Result<T, E> {
>Result : Symbol(Result, Decl(asyncYieldStarContextualType.ts, 0, 0))
>T : Symbol(T, Decl(asyncYieldStarContextualType.ts, 1, 17))
>E : Symbol(E, Decl(asyncYieldStarContextualType.ts, 1, 19))
[Symbol.iterator](): Generator<E, T, unknown>
>[Symbol.iterator] : Symbol(Result[Symbol.iterator], Decl(asyncYieldStarContextualType.ts, 1, 24))
>Symbol.iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
>iterator : Symbol(SymbolConstructor.iterator, Decl(lib.es2015.iterable.d.ts, --, --))
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
>E : Symbol(E, Decl(asyncYieldStarContextualType.ts, 1, 19))
>T : Symbol(T, Decl(asyncYieldStarContextualType.ts, 1, 17))
}
type Book = { id: string; title: string; authorId: string };
>Book : Symbol(Book, Decl(asyncYieldStarContextualType.ts, 3, 1))
>id : Symbol(id, Decl(asyncYieldStarContextualType.ts, 5, 13))
>title : Symbol(title, Decl(asyncYieldStarContextualType.ts, 5, 25))
>authorId : Symbol(authorId, Decl(asyncYieldStarContextualType.ts, 5, 40))
type Author = { id: string; name: string };
>Author : Symbol(Author, Decl(asyncYieldStarContextualType.ts, 5, 60))
>id : Symbol(id, Decl(asyncYieldStarContextualType.ts, 6, 15))
>name : Symbol(name, Decl(asyncYieldStarContextualType.ts, 6, 27))
type BookWithAuthor = Book & { author: Author };
>BookWithAuthor : Symbol(BookWithAuthor, Decl(asyncYieldStarContextualType.ts, 6, 43))
>Book : Symbol(Book, Decl(asyncYieldStarContextualType.ts, 3, 1))
>author : Symbol(author, Decl(asyncYieldStarContextualType.ts, 7, 30))
>Author : Symbol(Author, Decl(asyncYieldStarContextualType.ts, 5, 60))
declare const authorPromise: Promise<Result<Author, "NOT_FOUND_AUTHOR">>;
>authorPromise : Symbol(authorPromise, Decl(asyncYieldStarContextualType.ts, 9, 13))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>Result : Symbol(Result, Decl(asyncYieldStarContextualType.ts, 0, 0))
>Author : Symbol(Author, Decl(asyncYieldStarContextualType.ts, 5, 60))
declare const mapper: <T>(result: Result<T, "NOT_FOUND_AUTHOR">) => Result<T, "NOT_FOUND_AUTHOR">;
>mapper : Symbol(mapper, Decl(asyncYieldStarContextualType.ts, 10, 13))
>T : Symbol(T, Decl(asyncYieldStarContextualType.ts, 10, 23))
>result : Symbol(result, Decl(asyncYieldStarContextualType.ts, 10, 26))
>Result : Symbol(Result, Decl(asyncYieldStarContextualType.ts, 0, 0))
>T : Symbol(T, Decl(asyncYieldStarContextualType.ts, 10, 23))
>Result : Symbol(Result, Decl(asyncYieldStarContextualType.ts, 0, 0))
>T : Symbol(T, Decl(asyncYieldStarContextualType.ts, 10, 23))
declare const g: <T, U, V>() => AsyncGenerator<T, U, V>;
>g : Symbol(g, Decl(asyncYieldStarContextualType.ts, 11, 13))
>T : Symbol(T, Decl(asyncYieldStarContextualType.ts, 11, 18))
>U : Symbol(U, Decl(asyncYieldStarContextualType.ts, 11, 20))
>V : Symbol(V, Decl(asyncYieldStarContextualType.ts, 11, 23))
>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --))
>T : Symbol(T, Decl(asyncYieldStarContextualType.ts, 11, 18))
>U : Symbol(U, Decl(asyncYieldStarContextualType.ts, 11, 20))
>V : Symbol(V, Decl(asyncYieldStarContextualType.ts, 11, 23))
async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookWithAuthor, unknown> {
>f : Symbol(f, Decl(asyncYieldStarContextualType.ts, 11, 56))
>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --))
>BookWithAuthor : Symbol(BookWithAuthor, Decl(asyncYieldStarContextualType.ts, 6, 43))
// Without yield*, the type of test1 is
// Result<Author, "NOT_FOUND_AUTHOR>
const test1 = await authorPromise.then(mapper)
>test1 : Symbol(test1, Decl(asyncYieldStarContextualType.ts, 16, 9))
>authorPromise.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
>authorPromise : Symbol(authorPromise, Decl(asyncYieldStarContextualType.ts, 9, 13))
>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
>mapper : Symbol(mapper, Decl(asyncYieldStarContextualType.ts, 10, 13))
// With yield*, the type of test2 is
// Author | BookWithAuthor
// But this codepath has no way to produce BookWithAuthor
const test2 = yield* await authorPromise.then(mapper)
>test2 : Symbol(test2, Decl(asyncYieldStarContextualType.ts, 21, 9))
>authorPromise.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
>authorPromise : Symbol(authorPromise, Decl(asyncYieldStarContextualType.ts, 9, 13))
>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
>mapper : Symbol(mapper, Decl(asyncYieldStarContextualType.ts, 10, 13))
const x1 = yield* g();
>x1 : Symbol(x1, Decl(asyncYieldStarContextualType.ts, 23, 9))
>g : Symbol(g, Decl(asyncYieldStarContextualType.ts, 11, 13))
const x2: number = yield* g();
>x2 : Symbol(x2, Decl(asyncYieldStarContextualType.ts, 24, 9))
>g : Symbol(g, Decl(asyncYieldStarContextualType.ts, 11, 13))
return null! as BookWithAuthor;
>BookWithAuthor : Symbol(BookWithAuthor, Decl(asyncYieldStarContextualType.ts, 6, 43))
}

View File

@ -0,0 +1,123 @@
//// [tests/cases/compiler/asyncYieldStarContextualType.ts] ////
=== asyncYieldStarContextualType.ts ===
// https://github.com/microsoft/TypeScript/issues/57903
interface Result<T, E> {
[Symbol.iterator](): Generator<E, T, unknown>
>[Symbol.iterator] : () => Generator<E, T, unknown>
> : ^^^^^^
>Symbol.iterator : unique symbol
> : ^^^^^^^^^^^^^
>Symbol : SymbolConstructor
> : ^^^^^^^^^^^^^^^^^
>iterator : unique symbol
> : ^^^^^^^^^^^^^
}
type Book = { id: string; title: string; authorId: string };
>Book : Book
> : ^^^^
>id : string
> : ^^^^^^
>title : string
> : ^^^^^^
>authorId : string
> : ^^^^^^
type Author = { id: string; name: string };
>Author : Author
> : ^^^^^^
>id : string
> : ^^^^^^
>name : string
> : ^^^^^^
type BookWithAuthor = Book & { author: Author };
>BookWithAuthor : BookWithAuthor
> : ^^^^^^^^^^^^^^
>author : Author
> : ^^^^^^
declare const authorPromise: Promise<Result<Author, "NOT_FOUND_AUTHOR">>;
>authorPromise : Promise<Result<Author, "NOT_FOUND_AUTHOR">>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
declare const mapper: <T>(result: Result<T, "NOT_FOUND_AUTHOR">) => Result<T, "NOT_FOUND_AUTHOR">;
>mapper : <T>(result: Result<T, "NOT_FOUND_AUTHOR">) => Result<T, "NOT_FOUND_AUTHOR">
> : ^ ^^ ^^ ^^^^^
>result : Result<T, "NOT_FOUND_AUTHOR">
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
declare const g: <T, U, V>() => AsyncGenerator<T, U, V>;
>g : <T, U, V>() => AsyncGenerator<T, U, V>
> : ^ ^^ ^^ ^^^^^^^
async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookWithAuthor, unknown> {
>f : () => AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookWithAuthor, unknown>
> : ^^^^^^
// Without yield*, the type of test1 is
// Result<Author, "NOT_FOUND_AUTHOR>
const test1 = await authorPromise.then(mapper)
>test1 : Result<Author, "NOT_FOUND_AUTHOR">
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>await authorPromise.then(mapper) : Result<Author, "NOT_FOUND_AUTHOR">
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>authorPromise.then(mapper) : Promise<Result<Author, "NOT_FOUND_AUTHOR">>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>authorPromise.then : <TResult1 = Result<Author, "NOT_FOUND_AUTHOR">, TResult2 = never>(onfulfilled?: (value: Result<Author, "NOT_FOUND_AUTHOR">) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>authorPromise : Promise<Result<Author, "NOT_FOUND_AUTHOR">>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>then : <TResult1 = Result<Author, "NOT_FOUND_AUTHOR">, TResult2 = never>(onfulfilled?: (value: Result<Author, "NOT_FOUND_AUTHOR">) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>mapper : <T>(result: Result<T, "NOT_FOUND_AUTHOR">) => Result<T, "NOT_FOUND_AUTHOR">
> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// With yield*, the type of test2 is
// Author | BookWithAuthor
// But this codepath has no way to produce BookWithAuthor
const test2 = yield* await authorPromise.then(mapper)
>test2 : Author
> : ^^^^^^
>yield* await authorPromise.then(mapper) : Author
> : ^^^^^^
>await authorPromise.then(mapper) : Result<Author, "NOT_FOUND_AUTHOR">
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>authorPromise.then(mapper) : Promise<Result<Author, "NOT_FOUND_AUTHOR">>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>authorPromise.then : <TResult1 = Result<Author, "NOT_FOUND_AUTHOR">, TResult2 = never>(onfulfilled?: (value: Result<Author, "NOT_FOUND_AUTHOR">) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>authorPromise : Promise<Result<Author, "NOT_FOUND_AUTHOR">>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>then : <TResult1 = Result<Author, "NOT_FOUND_AUTHOR">, TResult2 = never>(onfulfilled?: (value: Result<Author, "NOT_FOUND_AUTHOR">) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>mapper : <T>(result: Result<T, "NOT_FOUND_AUTHOR">) => Result<T, "NOT_FOUND_AUTHOR">
> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const x1 = yield* g();
>x1 : unknown
> : ^^^^^^^
>yield* g() : unknown
> : ^^^^^^^
>g() : AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", unknown, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>g : <T, U, V>() => AsyncGenerator<T, U, V>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const x2: number = yield* g();
>x2 : number
> : ^^^^^^
>yield* g() : number
> : ^^^^^^
>g() : AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", number, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>g : <T, U, V>() => AsyncGenerator<T, U, V>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
return null! as BookWithAuthor;
>null! as BookWithAuthor : BookWithAuthor
> : ^^^^^^^^^^^^^^
>null! : null
> : ^^^^
}

View File

@ -0,0 +1,25 @@
//// [tests/cases/compiler/yieldStarContextualType.ts] ////
=== yieldStarContextualType.ts ===
declare const g: <T, U, V>() => Generator<T, U, V>;
>g : Symbol(g, Decl(yieldStarContextualType.ts, 0, 13))
>T : Symbol(T, Decl(yieldStarContextualType.ts, 0, 18))
>U : Symbol(U, Decl(yieldStarContextualType.ts, 0, 20))
>V : Symbol(V, Decl(yieldStarContextualType.ts, 0, 23))
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
>T : Symbol(T, Decl(yieldStarContextualType.ts, 0, 18))
>U : Symbol(U, Decl(yieldStarContextualType.ts, 0, 20))
>V : Symbol(V, Decl(yieldStarContextualType.ts, 0, 23))
function* f(): Generator<string, void, unknown> {
>f : Symbol(f, Decl(yieldStarContextualType.ts, 0, 51))
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
const x1 = yield* g();
>x1 : Symbol(x1, Decl(yieldStarContextualType.ts, 3, 9))
>g : Symbol(g, Decl(yieldStarContextualType.ts, 0, 13))
const x2: number = yield* g();
>x2 : Symbol(x2, Decl(yieldStarContextualType.ts, 4, 9))
>g : Symbol(g, Decl(yieldStarContextualType.ts, 0, 13))
}

View File

@ -0,0 +1,31 @@
//// [tests/cases/compiler/yieldStarContextualType.ts] ////
=== yieldStarContextualType.ts ===
declare const g: <T, U, V>() => Generator<T, U, V>;
>g : <T, U, V>() => Generator<T, U, V>
> : ^ ^^ ^^ ^^^^^^^
function* f(): Generator<string, void, unknown> {
>f : () => Generator<string, void, unknown>
> : ^^^^^^
const x1 = yield* g();
>x1 : unknown
> : ^^^^^^^
>yield* g() : unknown
> : ^^^^^^^
>g() : Generator<string, unknown, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>g : <T, U, V>() => Generator<T, U, V>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const x2: number = yield* g();
>x2 : number
> : ^^^^^^
>yield* g() : number
> : ^^^^^^
>g() : Generator<string, number, unknown>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>g : <T, U, V>() => Generator<T, U, V>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

View File

@ -0,0 +1,31 @@
// @target: esnext
// @noEmit: true
// https://github.com/microsoft/TypeScript/issues/57903
interface Result<T, E> {
[Symbol.iterator](): Generator<E, T, unknown>
}
type Book = { id: string; title: string; authorId: string };
type Author = { id: string; name: string };
type BookWithAuthor = Book & { author: Author };
declare const authorPromise: Promise<Result<Author, "NOT_FOUND_AUTHOR">>;
declare const mapper: <T>(result: Result<T, "NOT_FOUND_AUTHOR">) => Result<T, "NOT_FOUND_AUTHOR">;
declare const g: <T, U, V>() => AsyncGenerator<T, U, V>;
async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookWithAuthor, unknown> {
// Without yield*, the type of test1 is
// Result<Author, "NOT_FOUND_AUTHOR>
const test1 = await authorPromise.then(mapper)
// With yield*, the type of test2 is
// Author | BookWithAuthor
// But this codepath has no way to produce BookWithAuthor
const test2 = yield* await authorPromise.then(mapper)
const x1 = yield* g();
const x2: number = yield* g();
return null! as BookWithAuthor;
}

View File

@ -0,0 +1,9 @@
// @target: esnext
// @noEmit: true
declare const g: <T, U, V>() => Generator<T, U, V>;
function* f(): Generator<string, void, unknown> {
const x1 = yield* g();
const x2: number = yield* g();
}