Skip to content

Commit 44777b9

Browse files
committed
Contextual typing for yield expressions
1 parent 95bfd7c commit 44777b9

File tree

1 file changed

+34
-12
lines changed

1 file changed

+34
-12
lines changed

src/compiler/checker.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5704,20 +5704,41 @@ module ts {
57045704
}
57055705

57065706
function getContextualTypeForReturnExpression(node: Expression): Type {
5707+
let func = getContainingFunction(node);
5708+
if (func && !func.asteriskToken) {
5709+
return getContextualReturnType(func);
5710+
}
5711+
5712+
return undefined;
5713+
}
5714+
5715+
function getContextualTypeForYieldOperand(node: YieldExpression): Type {
57075716
let func = getContainingFunction(node);
57085717
if (func) {
5709-
// If the containing function has a return type annotation, is a constructor, or is a get accessor whose
5710-
// corresponding set accessor has a type annotation, return statements in the function are contextually typed
5711-
if (func.type || func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(<AccessorDeclaration>getDeclarationOfKind(func.symbol, SyntaxKind.SetAccessor))) {
5712-
return getReturnTypeOfSignature(getSignatureFromDeclaration(func));
5713-
}
5714-
// Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
5715-
// and that call signature is non-generic, return statements are contextually typed by the return type of the signature
5716-
let signature = getContextualSignatureForFunctionLikeDeclaration(<FunctionExpression>func);
5717-
if (signature) {
5718-
return getReturnTypeOfSignature(signature);
5718+
let contextualReturnType = getContextualReturnType(func);
5719+
if (contextualReturnType) {
5720+
return node.asteriskToken
5721+
? contextualReturnType
5722+
: getElementTypeFromIterableIterator(contextualReturnType, /*errorNode*/ undefined);
57195723
}
57205724
}
5725+
5726+
return undefined;
5727+
}
5728+
5729+
function getContextualReturnType(functionDecl: FunctionLikeDeclaration): Type {
5730+
// If the containing function has a return type annotation, is a constructor, or is a get accessor whose
5731+
// corresponding set accessor has a type annotation, return statements in the function are contextually typed
5732+
if (functionDecl.type || functionDecl.kind === SyntaxKind.Constructor || functionDecl.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(<AccessorDeclaration>getDeclarationOfKind(functionDecl.symbol, SyntaxKind.SetAccessor))) {
5733+
return getReturnTypeOfSignature(getSignatureFromDeclaration(functionDecl));
5734+
}
5735+
// Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
5736+
// and that call signature is non-generic, return statements are contextually typed by the return type of the signature
5737+
let signature = getContextualSignatureForFunctionLikeDeclaration(<FunctionExpression>functionDecl);
5738+
if (signature) {
5739+
return getReturnTypeOfSignature(signature);
5740+
}
5741+
57215742
return undefined;
57225743
}
57235744

@@ -5887,6 +5908,8 @@ module ts {
58875908
case SyntaxKind.ArrowFunction:
58885909
case SyntaxKind.ReturnStatement:
58895910
return getContextualTypeForReturnExpression(node);
5911+
case SyntaxKind.YieldExpression:
5912+
return getContextualTypeForYieldOperand(<YieldExpression>parent);
58905913
case SyntaxKind.CallExpression:
58915914
case SyntaxKind.NewExpression:
58925915
return getContextualTypeForArgument(<CallExpression>parent, node);
@@ -7912,7 +7935,7 @@ module ts {
79127935
// Also, there is no point in doing an assignability check if the function
79137936
// has no explicit return type, because the return type is directly computed
79147937
// from the yield expressions.
7915-
if (func.asteriskToken && func.type) {
7938+
if (func && func.asteriskToken && func.type) {
79167939
let signatureElementType = getElementTypeFromIterableIterator(getTypeFromTypeNode(func.type), /*errorNode*/ undefined) || unknownType;
79177940
let expressionType = checkExpressionCached(node.expression, /*contextualMapper*/ undefined);
79187941
if (node.asteriskToken) {
@@ -9533,7 +9556,6 @@ module ts {
95339556
}
95349557

95359558
function getElementTypeFromIterable(iterable: Type, errorNode: Node): Type {
9536-
Debug.assert(languageVersion >= ScriptTarget.ES6);
95379559
// We want to treat type as an iterable, and get the type it is an iterable of. The iterable
95389560
// must have the following structure (annotated with the names of the variables below):
95399561
//

0 commit comments

Comments
 (0)