@@ -5508,6 +5508,10 @@ namespace ts {
5508
5508
return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow;
5509
5509
}
5510
5510
5511
+ function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | MethodDeclaration {
5512
+ return (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) && isContextSensitiveFunctionLikeDeclaration(func);
5513
+ }
5514
+
5511
5515
function getTypeWithoutSignatures(type: Type): Type {
5512
5516
if (type.flags & TypeFlags.ObjectType) {
5513
5517
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
@@ -8179,6 +8183,21 @@ namespace ts {
8179
8183
captureLexicalThis(node, container);
8180
8184
}
8181
8185
if (isFunctionLike(container)) {
8186
+ // If this is a function in a JS file, it might be a class method. Check if it's the RHS
8187
+ // of a x.prototype.y = function [name]() { .... }
8188
+ if (container.kind === SyntaxKind.FunctionExpression &&
8189
+ isInJavaScriptFile(container.parent) &&
8190
+ getSpecialPropertyAssignmentKind(container.parent) === SpecialPropertyAssignmentKind.PrototypeProperty) {
8191
+ // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container')
8192
+ const className = (((container.parent as BinaryExpression) // x.prototype.y = f
8193
+ .left as PropertyAccessExpression) // x.prototype.y
8194
+ .expression as PropertyAccessExpression) // x.prototype
8195
+ .expression; // x
8196
+ const classSymbol = checkExpression(className).symbol;
8197
+ if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) {
8198
+ return getInferredClassType(classSymbol);
8199
+ }
8200
+ }
8182
8201
const type = getContextuallyTypedThisType(container);
8183
8202
if (type) {
8184
8203
return type;
@@ -8207,22 +8226,6 @@ namespace ts {
8207
8226
if (type && type !== unknownType) {
8208
8227
return type;
8209
8228
}
8210
-
8211
- // If this is a function in a JS file, it might be a class method. Check if it's the RHS
8212
- // of a x.prototype.y = function [name]() { .... }
8213
- if (container.kind === SyntaxKind.FunctionExpression) {
8214
- if (getSpecialPropertyAssignmentKind(container.parent) === SpecialPropertyAssignmentKind.PrototypeProperty) {
8215
- // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container')
8216
- const className = (((container.parent as BinaryExpression) // x.prototype.y = f
8217
- .left as PropertyAccessExpression) // x.prototype.y
8218
- .expression as PropertyAccessExpression) // x.prototype
8219
- .expression; // x
8220
- const classSymbol = checkExpression(className).symbol;
8221
- if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) {
8222
- return getInferredClassType(classSymbol);
8223
- }
8224
- }
8225
- }
8226
8229
}
8227
8230
8228
8231
if (compilerOptions.noImplicitThis) {
@@ -8447,12 +8450,13 @@ namespace ts {
8447
8450
}
8448
8451
8449
8452
function getContextuallyTypedThisType(func: FunctionLikeDeclaration): Type {
8450
- if ((isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) &&
8451
- isContextSensitive(func) &&
8452
- func.kind !== SyntaxKind.ArrowFunction) {
8453
+ if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
8453
8454
const contextualSignature = getContextualSignature(func);
8454
8455
if (contextualSignature) {
8455
- return contextualSignature.thisType;
8456
+ return contextualSignature.thisType || anyType;
8457
+ }
8458
+ else if (getContextualTypeForFunctionLikeDeclaration(func) === anyType) {
8459
+ return anyType;
8456
8460
}
8457
8461
}
8458
8462
@@ -8462,34 +8466,31 @@ namespace ts {
8462
8466
// Return contextual type of parameter or undefined if no contextual type is available
8463
8467
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
8464
8468
const func = parameter.parent;
8465
- if (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) {
8466
- if (isContextSensitive(func)) {
8467
- const contextualSignature = getContextualSignature(func);
8468
- if (contextualSignature) {
8469
-
8470
- const funcHasRestParameters = hasRestParameter(func);
8471
- const len = func.parameters.length - (funcHasRestParameters ? 1 : 0);
8472
- const indexOfParameter = indexOf(func.parameters, parameter);
8473
- if (indexOfParameter < len) {
8474
- return getTypeAtPosition(contextualSignature, indexOfParameter);
8475
- }
8469
+ if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
8470
+ const contextualSignature = getContextualSignature(func);
8471
+ if (contextualSignature) {
8472
+ const funcHasRestParameters = hasRestParameter(func);
8473
+ const len = func.parameters.length - (funcHasRestParameters ? 1 : 0);
8474
+ const indexOfParameter = indexOf(func.parameters, parameter);
8475
+ if (indexOfParameter < len) {
8476
+ return getTypeAtPosition(contextualSignature, indexOfParameter);
8477
+ }
8476
8478
8477
- // If last parameter is contextually rest parameter get its type
8478
- if (funcHasRestParameters &&
8479
- indexOfParameter === (func.parameters.length - 1) &&
8480
- isRestParameterIndex(contextualSignature, func.parameters.length - 1)) {
8481
- return getTypeOfSymbol(lastOrUndefined(contextualSignature.parameters));
8482
- }
8479
+ // If last parameter is contextually rest parameter get its type
8480
+ if (funcHasRestParameters &&
8481
+ indexOfParameter === (func.parameters.length - 1) &&
8482
+ isRestParameterIndex(contextualSignature, func.parameters.length - 1)) {
8483
+ return getTypeOfSymbol(lastOrUndefined(contextualSignature.parameters));
8483
8484
}
8484
8485
}
8485
8486
}
8486
8487
return undefined;
8487
8488
}
8488
8489
8489
8490
// In a variable, parameter or property declaration with a type annotation,
8490
- // the contextual type of an initializer expression is the type of the variable, parameter or property.
8491
- // Otherwise, in a parameter declaration of a contextually typed function expression,
8492
- // the contextual type of an initializer expression is the contextual type of the parameter.
8491
+ // the contextual type of an initializer expression is the type of the variable, parameter or property.
8492
+ // Otherwise, in a parameter declaration of a contextually typed function expression,
8493
+ // the contextual type of an initializer expression is the contextual type of the parameter.
8493
8494
// Otherwise, in a variable or parameter declaration with a binding pattern name,
8494
8495
// the contextual type of an initializer expression is the type implied by the binding pattern.
8495
8496
// Otherwise, in a binding pattern inside a variable or parameter declaration,
@@ -8843,16 +8844,20 @@ namespace ts {
8843
8844
: undefined;
8844
8845
}
8845
8846
8847
+ function getContextualTypeForFunctionLikeDeclaration(node: FunctionExpression | MethodDeclaration) {
8848
+ return isObjectLiteralMethod(node)
8849
+ ? getContextualTypeForObjectLiteralMethod(node)
8850
+ : getApparentTypeOfContextualType(node);
8851
+ }
8852
+
8846
8853
// Return the contextual signature for a given expression node. A contextual type provides a
8847
8854
// contextual signature if it has a single call signature and if that call signature is non-generic.
8848
8855
// If the contextual type is a union type, get the signature from each type possible and if they are
8849
8856
// all identical ignoring their return type, the result is same signature but with return type as
8850
8857
// union type of return types from these signatures
8851
8858
function getContextualSignature(node: FunctionExpression | MethodDeclaration): Signature {
8852
8859
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
8853
- const type = isObjectLiteralMethod(node)
8854
- ? getContextualTypeForObjectLiteralMethod(node)
8855
- : getApparentTypeOfContextualType(node);
8860
+ const type = getContextualTypeForFunctionLikeDeclaration(node);
8856
8861
if (!type) {
8857
8862
return undefined;
8858
8863
}
0 commit comments