Merge pull request #8483 from Microsoft/contextually-type-iife-parameters

Contextually type IIFE params by their arguments
This commit is contained in:
Nathan Shively-Sanders
2016-05-05 20:41:08 -07:00
5 changed files with 537 additions and 3 deletions
+31 -3
View File
@@ -8539,6 +8539,20 @@ namespace ts {
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
const func = parameter.parent;
if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
const iife = getImmediatelyInvokedFunctionExpression(func);
if (iife) {
const indexOfParameter = indexOf(func.parameters, parameter);
if (iife.arguments && indexOfParameter < iife.arguments.length) {
if (parameter.dotDotDotToken) {
const restTypes: Type[] = [];
for (let i = indexOfParameter; i < iife.arguments.length; i++) {
restTypes.push(getTypeOfExpression(iife.arguments[i]));
}
return createArrayType(getUnionType(restTypes));
}
return checkExpression(iife.arguments[indexOfParameter]);
}
}
const contextualSignature = getContextualSignature(func);
if (contextualSignature) {
const funcHasRestParameters = hasRestParameter(func);
@@ -8559,6 +8573,20 @@ namespace ts {
return undefined;
}
function getImmediatelyInvokedFunctionExpression(func: FunctionExpression | MethodDeclaration) {
if (isFunctionExpressionOrArrowFunction(func)) {
let prev: Node = func;
let parent: Node = func.parent;
while (parent.kind === SyntaxKind.ParenthesizedExpression) {
prev = parent;
parent = parent.parent;
}
if (parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === prev) {
return parent as CallExpression;
}
}
}
// In a variable, parameter or property declaration with a type annotation,
// the contextual type of an initializer expression is the type of the variable, parameter or property.
// Otherwise, in a parameter declaration of a contextually typed function expression,
@@ -8917,9 +8945,9 @@ namespace ts {
}
function getContextualTypeForFunctionLikeDeclaration(node: FunctionExpression | MethodDeclaration) {
return isObjectLiteralMethod(node)
? getContextualTypeForObjectLiteralMethod(node)
: getApparentTypeOfContextualType(node);
return isObjectLiteralMethod(node) ?
getContextualTypeForObjectLiteralMethod(node) :
getApparentTypeOfContextualType(node);
}
// Return the contextual signature for a given expression node. A contextual type provides a