diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9c5beffc61130..04f0221c1eeed 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -921,6 +921,7 @@ namespace ts { let globalBooleanType: ObjectType; let globalRegExpType: ObjectType; let globalThisType: GenericType; + let globalYieldType: GenericType; let anyArrayType: Type; let autoArrayType: Type; let anyReadonlyArrayType: Type; @@ -25875,6 +25876,16 @@ namespace ts { }); } + function getYieldTypeArgument(type: Type): Type | undefined { + return getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).target === globalYieldType ? getTypeArguments(type as TypeReference)[0] : undefined; + } + + function getYieldTypeFromContextualType(type: Type): Type | undefined { + return mapType(type, t => { + return t.flags & TypeFlags.Intersection ? forEach((t as IntersectionType).types, getYieldTypeArgument) : getYieldTypeArgument(t); + }); + } + function getContextualThisParameterType(func: SignatureDeclaration): Type | undefined { if (func.kind === SyntaxKind.ArrowFunction) { return undefined; @@ -33603,6 +33614,11 @@ namespace ts { return getIterationTypeOfIterable(use, IterationTypeKind.Return, yieldExpressionType, node.expression) || anyType; } + + const suggestedReturnType = yieldedType && getYieldTypeFromContextualType(yieldedType); + if (suggestedReturnType) { + return suggestedReturnType; + } else if (returnType) { return getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Next, returnType, isAsync) || anyType; @@ -42399,6 +42415,7 @@ namespace ts { globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1) as GenericType || globalArrayType; anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1) as GenericType; + globalYieldType = getGlobalTypeOrUndefined("YieldType" as __String, /*arity*/ 1) as GenericType; if (augmentations) { // merge _nonglobal_ module augmentations. diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 8fdd386af1e61..63faeae31bc82 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -1145,6 +1145,7 @@ namespace FourSlashInterface { typeEntry("Capitalize"), typeEntry("Uncapitalize"), interfaceEntry("ThisType"), + interfaceEntry("YieldType"), varEntry("ArrayBuffer"), interfaceEntry("ArrayBufferTypes"), typeEntry("ArrayBufferLike"), diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 1cd4cdd7412d2..14756f4ebe74c 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -1605,6 +1605,11 @@ type Uncapitalize<S extends string> = intrinsic; */ interface ThisType<T> { } +/** + * Marker for yield expressions return types + */ +interface YieldType<T> { } + /** * Represents a raw buffer of binary data, which is used to store data for the * different typed arrays. ArrayBuffers cannot be read from or written to directly, diff --git a/tests/baselines/reference/generatorReturnTypeInference.types b/tests/baselines/reference/generatorReturnTypeInference.types index a0942c9b70003..f401cb46a7429 100644 --- a/tests/baselines/reference/generatorReturnTypeInference.types +++ b/tests/baselines/reference/generatorReturnTypeInference.types @@ -69,7 +69,7 @@ function* g007() { // Generator<never, void, unknown> >g007 : () => Generator<never, void, unknown> yield never; ->yield never : any +>yield never : never >never : never } diff --git a/tests/baselines/reference/generatorReturnTypeInferenceNonStrict.types b/tests/baselines/reference/generatorReturnTypeInferenceNonStrict.types index 4d6754d85bf62..bac21479af2fa 100644 --- a/tests/baselines/reference/generatorReturnTypeInferenceNonStrict.types +++ b/tests/baselines/reference/generatorReturnTypeInferenceNonStrict.types @@ -71,7 +71,7 @@ function* g007() { // Generator<never, void, unknown> >g007 : () => Generator<never, void, unknown> yield never; ->yield never : any +>yield never : never >never : never }