@@ -3144,8 +3144,7 @@ namespace ts {
3144
3144
// Use contextual parameter type if one is available
3145
3145
let type: Type;
3146
3146
if (declaration.symbol.name === "this") {
3147
- const thisParameter = getContextualThisParameter(func);
3148
- type = thisParameter ? getTypeOfSymbol(thisParameter) : undefined;
3147
+ type = getContextualThisParameterType(func);
3149
3148
}
3150
3149
else {
3151
3150
type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
@@ -4789,9 +4788,6 @@ namespace ts {
4789
4788
if (isJSConstructSignature) {
4790
4789
minArgumentCount--;
4791
4790
}
4792
- if (!thisParameter && isObjectLiteralMethod(declaration)) {
4793
- thisParameter = getContextualThisParameter(declaration);
4794
- }
4795
4791
4796
4792
const classType = declaration.kind === SyntaxKind.Constructor ?
4797
4793
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
@@ -6101,9 +6097,24 @@ namespace ts {
6101
6097
}
6102
6098
6103
6099
function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) {
6104
- const areAllParametersUntyped = !forEach(node.parameters, p => p.type);
6105
- const isNullaryArrow = node.kind === SyntaxKind.ArrowFunction && !node.parameters.length;
6106
- return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow;
6100
+ // Functions with type parameters are not context sensitive.
6101
+ if (node.typeParameters) {
6102
+ return false;
6103
+ }
6104
+ // Functions with any parameters that lack type annotations are context sensitive.
6105
+ if (forEach(node.parameters, p => !p.type)) {
6106
+ return true;
6107
+ }
6108
+ // For arrow functions we now know we're not context sensitive.
6109
+ if (node.kind === SyntaxKind.ArrowFunction) {
6110
+ return false;
6111
+ }
6112
+ // If the first parameter is not an explicit 'this' parameter, then the function has
6113
+ // an implicit 'this' parameter which is subject to contextual typing. Otherwise we
6114
+ // know that all parameters (including 'this') have type annotations and nothing is
6115
+ // subject to contextual typing.
6116
+ const parameter = firstOrUndefined(node.parameters);
6117
+ return !(parameter && parameter.name.kind === SyntaxKind.Identifier && (<Identifier>parameter.name).text === "this");
6107
6118
}
6108
6119
6109
6120
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {
@@ -9629,7 +9640,7 @@ namespace ts {
9629
9640
}
9630
9641
}
9631
9642
9632
- const thisType = getThisTypeOfDeclaration(container);
9643
+ let thisType = getThisTypeOfDeclaration(container) || getContextualThisParameterType (container);
9633
9644
if (thisType) {
9634
9645
return thisType;
9635
9646
}
@@ -9869,14 +9880,16 @@ namespace ts {
9869
9880
}
9870
9881
}
9871
9882
9872
- function getContextualThisParameter (func: FunctionLikeDeclaration): Symbol {
9883
+ function getContextualThisParameterType (func: FunctionLikeDeclaration): Type {
9873
9884
if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
9874
9885
const contextualSignature = getContextualSignature(func);
9875
9886
if (contextualSignature) {
9876
- return contextualSignature.thisParameter;
9887
+ const thisParameter = contextualSignature.thisParameter;
9888
+ if (thisParameter) {
9889
+ return getTypeOfSymbol(thisParameter);
9890
+ }
9877
9891
}
9878
9892
}
9879
-
9880
9893
return undefined;
9881
9894
}
9882
9895
@@ -12840,21 +12853,36 @@ namespace ts {
12840
12853
12841
12854
function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) {
12842
12855
const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
12856
+ if (isInferentialContext(mapper)) {
12857
+ for (let i = 0; i < len; i++) {
12858
+ const declaration = <ParameterDeclaration>signature.parameters[i].valueDeclaration;
12859
+ if (declaration.type) {
12860
+ inferTypes(mapper.context, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
12861
+ }
12862
+ }
12863
+ }
12843
12864
if (context.thisParameter) {
12844
- if (!signature.thisParameter) {
12845
- signature.thisParameter = createTransientSymbol(context.thisParameter, undefined);
12865
+ const parameter = signature.thisParameter;
12866
+ if (!parameter || parameter.valueDeclaration && !(<ParameterDeclaration>parameter.valueDeclaration).type) {
12867
+ if (!parameter) {
12868
+ signature.thisParameter = createTransientSymbol(context.thisParameter, undefined);
12869
+ }
12870
+ assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper);
12846
12871
}
12847
- assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper);
12848
12872
}
12849
12873
for (let i = 0; i < len; i++) {
12850
12874
const parameter = signature.parameters[i];
12851
- const contextualParameterType = getTypeAtPosition(context, i);
12852
- assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
12875
+ if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
12876
+ const contextualParameterType = getTypeAtPosition(context, i);
12877
+ assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
12878
+ }
12853
12879
}
12854
12880
if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) {
12855
12881
const parameter = lastOrUndefined(signature.parameters);
12856
- const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
12857
- assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
12882
+ if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
12883
+ const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
12884
+ assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
12885
+ }
12858
12886
}
12859
12887
}
12860
12888
0 commit comments