From fdf0095adba6d28b6012240f5fa8595ac4a1af6f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 22 May 2024 14:54:28 -0400 Subject: [PATCH 1/2] Do not infer yield* type from contextual TReturn --- src/compiler/checker.ts | 22 +++-- .../asyncYieldStarContextualType.symbols | 78 +++++++++++++++ .../asyncYieldStarContextualType.types | 99 +++++++++++++++++++ .../compiler/asyncYieldStarContextualType.ts | 27 +++++ 4 files changed, 220 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/asyncYieldStarContextualType.symbols create mode 100644 tests/baselines/reference/asyncYieldStarContextualType.types create mode 100644 tests/cases/compiler/asyncYieldStarContextualType.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2a914ab0ec325..3585ebc379d52 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -30839,9 +30839,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); } } @@ -37753,7 +37763,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isGenerator) { - return createGeneratorReturnType( + return createGeneratorType( yieldType || neverType, returnType || fallbackReturnType, nextType || getContextualIterationType(IterationTypeKind.Next, func) || unknownType, @@ -37770,7 +37780,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; @@ -40572,7 +40582,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); } diff --git a/tests/baselines/reference/asyncYieldStarContextualType.symbols b/tests/baselines/reference/asyncYieldStarContextualType.symbols new file mode 100644 index 0000000000000..671798c017885 --- /dev/null +++ b/tests/baselines/reference/asyncYieldStarContextualType.symbols @@ -0,0 +1,78 @@ +//// [tests/cases/compiler/asyncYieldStarContextualType.ts] //// + +=== asyncYieldStarContextualType.ts === +// https://github.com/microsoft/TypeScript/issues/57903 +interface Result { +>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 +>[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>; +>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: (result: Result) => Result; +>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)) + +async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookWithAuthor, unknown> { +>f : Symbol(f, Decl(asyncYieldStarContextualType.ts, 10, 98)) +>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 + const test1 = await authorPromise.then(mapper) +>test1 : Symbol(test1, Decl(asyncYieldStarContextualType.ts, 15, 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, 20, 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)) + + return null! as BookWithAuthor; +>BookWithAuthor : Symbol(BookWithAuthor, Decl(asyncYieldStarContextualType.ts, 6, 43)) +} diff --git a/tests/baselines/reference/asyncYieldStarContextualType.types b/tests/baselines/reference/asyncYieldStarContextualType.types new file mode 100644 index 0000000000000..e5b13791486c2 --- /dev/null +++ b/tests/baselines/reference/asyncYieldStarContextualType.types @@ -0,0 +1,99 @@ +//// [tests/cases/compiler/asyncYieldStarContextualType.ts] //// + +=== asyncYieldStarContextualType.ts === +// https://github.com/microsoft/TypeScript/issues/57903 +interface Result { + [Symbol.iterator](): Generator +>[Symbol.iterator] : () => Generator +> : ^^^^^^ +>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>; +>authorPromise : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +declare const mapper: (result: Result) => Result; +>mapper : (result: Result) => Result +> : ^ ^^ ^^ ^^^^^ +>result : Result +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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 + const test1 = await authorPromise.then(mapper) +>test1 : Result +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>await authorPromise.then(mapper) : Result +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>authorPromise.then(mapper) : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>authorPromise.then : , TResult2 = never>(onfulfilled?: (value: Result) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>authorPromise : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>then : , TResult2 = never>(onfulfilled?: (value: Result) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mapper : (result: Result) => Result +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + // 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 +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>authorPromise.then(mapper) : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>authorPromise.then : , TResult2 = never>(onfulfilled?: (value: Result) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>authorPromise : Promise> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>then : , TResult2 = never>(onfulfilled?: (value: Result) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike) => Promise +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>mapper : (result: Result) => Result +> : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + return null! as BookWithAuthor; +>null! as BookWithAuthor : BookWithAuthor +> : ^^^^^^^^^^^^^^ +>null! : null +> : ^^^^ +} diff --git a/tests/cases/compiler/asyncYieldStarContextualType.ts b/tests/cases/compiler/asyncYieldStarContextualType.ts new file mode 100644 index 0000000000000..54cf5d3522eaf --- /dev/null +++ b/tests/cases/compiler/asyncYieldStarContextualType.ts @@ -0,0 +1,27 @@ +// @target: esnext +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/57903 +interface Result { + [Symbol.iterator](): Generator +} + +type Book = { id: string; title: string; authorId: string }; +type Author = { id: string; name: string }; +type BookWithAuthor = Book & { author: Author }; + +declare const authorPromise: Promise>; +declare const mapper: (result: Result) => Result; + +async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookWithAuthor, unknown> { + // Without yield*, the type of test1 is + // Result + 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) + + return null! as BookWithAuthor; +} \ No newline at end of file From d6bdb1a1708d87b4b7d4275fe79cd564dbcd884d Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 22 May 2024 15:14:12 -0400 Subject: [PATCH 2/2] Additional contextual type tests --- .../asyncYieldStarContextualType.symbols | 24 ++++++++++++-- .../asyncYieldStarContextualType.types | 24 ++++++++++++++ .../reference/yieldStarContextualType.symbols | 25 +++++++++++++++ .../reference/yieldStarContextualType.types | 31 +++++++++++++++++++ .../compiler/asyncYieldStarContextualType.ts | 4 +++ .../cases/compiler/yieldStarContextualType.ts | 9 ++++++ 6 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/yieldStarContextualType.symbols create mode 100644 tests/baselines/reference/yieldStarContextualType.types create mode 100644 tests/cases/compiler/yieldStarContextualType.ts diff --git a/tests/baselines/reference/asyncYieldStarContextualType.symbols b/tests/baselines/reference/asyncYieldStarContextualType.symbols index 671798c017885..364801f5494aa 100644 --- a/tests/baselines/reference/asyncYieldStarContextualType.symbols +++ b/tests/baselines/reference/asyncYieldStarContextualType.symbols @@ -49,15 +49,25 @@ declare const mapper: (result: Result) => ResultResult : Symbol(Result, Decl(asyncYieldStarContextualType.ts, 0, 0)) >T : Symbol(T, Decl(asyncYieldStarContextualType.ts, 10, 23)) +declare const g: () => AsyncGenerator; +>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, 10, 98)) +>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 const test1 = await authorPromise.then(mapper) ->test1 : Symbol(test1, Decl(asyncYieldStarContextualType.ts, 15, 9)) +>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, --, --)) @@ -67,12 +77,20 @@ async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookW // Author | BookWithAuthor // But this codepath has no way to produce BookWithAuthor const test2 = yield* await authorPromise.then(mapper) ->test2 : Symbol(test2, Decl(asyncYieldStarContextualType.ts, 20, 9)) +>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)) } diff --git a/tests/baselines/reference/asyncYieldStarContextualType.types b/tests/baselines/reference/asyncYieldStarContextualType.types index e5b13791486c2..0a340b75589ad 100644 --- a/tests/baselines/reference/asyncYieldStarContextualType.types +++ b/tests/baselines/reference/asyncYieldStarContextualType.types @@ -48,6 +48,10 @@ declare const mapper: (result: Result) => Resultresult : Result > : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +declare const g: () => AsyncGenerator; +>g : () => AsyncGenerator +> : ^ ^^ ^^ ^^^^^^^ + async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookWithAuthor, unknown> { >f : () => AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookWithAuthor, unknown> > : ^^^^^^ @@ -91,6 +95,26 @@ async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookW >mapper : (result: Result) => Result > : ^ ^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + const x1 = yield* g(); +>x1 : unknown +> : ^^^^^^^ +>yield* g() : unknown +> : ^^^^^^^ +>g() : AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", unknown, unknown> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>g : () => AsyncGenerator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const x2: number = yield* g(); +>x2 : number +> : ^^^^^^ +>yield* g() : number +> : ^^^^^^ +>g() : AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", number, unknown> +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>g : () => AsyncGenerator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + return null! as BookWithAuthor; >null! as BookWithAuthor : BookWithAuthor > : ^^^^^^^^^^^^^^ diff --git a/tests/baselines/reference/yieldStarContextualType.symbols b/tests/baselines/reference/yieldStarContextualType.symbols new file mode 100644 index 0000000000000..42ddeddabfd19 --- /dev/null +++ b/tests/baselines/reference/yieldStarContextualType.symbols @@ -0,0 +1,25 @@ +//// [tests/cases/compiler/yieldStarContextualType.ts] //// + +=== yieldStarContextualType.ts === +declare const g: () => Generator; +>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 { +>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)) +} diff --git a/tests/baselines/reference/yieldStarContextualType.types b/tests/baselines/reference/yieldStarContextualType.types new file mode 100644 index 0000000000000..08f89242fda8c --- /dev/null +++ b/tests/baselines/reference/yieldStarContextualType.types @@ -0,0 +1,31 @@ +//// [tests/cases/compiler/yieldStarContextualType.ts] //// + +=== yieldStarContextualType.ts === +declare const g: () => Generator; +>g : () => Generator +> : ^ ^^ ^^ ^^^^^^^ + +function* f(): Generator { +>f : () => Generator +> : ^^^^^^ + + const x1 = yield* g(); +>x1 : unknown +> : ^^^^^^^ +>yield* g() : unknown +> : ^^^^^^^ +>g() : Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>g : () => Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const x2: number = yield* g(); +>x2 : number +> : ^^^^^^ +>yield* g() : number +> : ^^^^^^ +>g() : Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>g : () => Generator +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} diff --git a/tests/cases/compiler/asyncYieldStarContextualType.ts b/tests/cases/compiler/asyncYieldStarContextualType.ts index 54cf5d3522eaf..df6968de10ad6 100644 --- a/tests/cases/compiler/asyncYieldStarContextualType.ts +++ b/tests/cases/compiler/asyncYieldStarContextualType.ts @@ -12,6 +12,7 @@ type BookWithAuthor = Book & { author: Author }; declare const authorPromise: Promise>; declare const mapper: (result: Result) => Result; +declare const g: () => AsyncGenerator; async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookWithAuthor, unknown> { // Without yield*, the type of test1 is @@ -23,5 +24,8 @@ async function* f(): AsyncGenerator<"NOT_FOUND_AUTHOR" | "NOT_FOUND_BOOK", BookW // 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; } \ No newline at end of file diff --git a/tests/cases/compiler/yieldStarContextualType.ts b/tests/cases/compiler/yieldStarContextualType.ts new file mode 100644 index 0000000000000..a8ccd165a25ab --- /dev/null +++ b/tests/cases/compiler/yieldStarContextualType.ts @@ -0,0 +1,9 @@ +// @target: esnext +// @noEmit: true + +declare const g: () => Generator; + +function* f(): Generator { + const x1 = yield* g(); + const x2: number = yield* g(); +} \ No newline at end of file