@@ -2406,7 +2406,7 @@ namespace ts {
2406
2406
2407
2407
// If the declaration specifies a binding pattern, use the type implied by the binding pattern
2408
2408
if (isBindingPattern(declaration.name)) {
2409
- return getTypeFromBindingPattern(<BindingPattern>declaration.name);
2409
+ return getTypeFromBindingPattern(<BindingPattern>declaration.name, /*includePatternInType*/ false );
2410
2410
}
2411
2411
2412
2412
// No type specified and nothing can be inferred
@@ -2421,13 +2421,13 @@ namespace ts {
2421
2421
return getWidenedType(checkExpressionCached(element.initializer));
2422
2422
}
2423
2423
if (isBindingPattern(element.name)) {
2424
- return getTypeFromBindingPattern(<BindingPattern>element.name);
2424
+ return getTypeFromBindingPattern(<BindingPattern>element.name, /*includePatternInType*/ false );
2425
2425
}
2426
2426
return anyType;
2427
2427
}
2428
2428
2429
2429
// Return the type implied by an object binding pattern
2430
- function getTypeFromObjectBindingPattern(pattern: BindingPattern): Type {
2430
+ function getTypeFromObjectBindingPattern(pattern: BindingPattern, includePatternInType: boolean ): Type {
2431
2431
let members: SymbolTable = {};
2432
2432
forEach(pattern.elements, e => {
2433
2433
let flags = SymbolFlags.Property | SymbolFlags.Transient | (e.initializer ? SymbolFlags.Optional : 0);
@@ -2436,28 +2436,27 @@ namespace ts {
2436
2436
symbol.type = getTypeFromBindingElement(e);
2437
2437
members[symbol.name] = symbol;
2438
2438
});
2439
- return createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined);
2439
+ let result = createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined);
2440
+ if (includePatternInType) {
2441
+ result.pattern = pattern;
2442
+ }
2443
+ return result;
2440
2444
}
2441
2445
2442
2446
// Return the type implied by an array binding pattern
2443
- function getTypeFromArrayBindingPattern(pattern: BindingPattern): Type {
2444
- let hasSpreadElement: boolean = false;
2445
- let elementTypes: Type[] = [];
2446
- forEach(pattern.elements, e => {
2447
- elementTypes.push(e.kind === SyntaxKind.OmittedExpression || e.dotDotDotToken ? anyType : getTypeFromBindingElement(e));
2448
- if (e.dotDotDotToken) {
2449
- hasSpreadElement = true;
2450
- }
2451
- });
2452
- if (!elementTypes.length) {
2447
+ function getTypeFromArrayBindingPattern(pattern: BindingPattern, includePatternInType: boolean): Type {
2448
+ let elements = pattern.elements;
2449
+ if (elements.length === 0 || elements[elements.length - 1].dotDotDotToken) {
2453
2450
return languageVersion >= ScriptTarget.ES6 ? createIterableType(anyType) : anyArrayType;
2454
2451
}
2455
- else if (hasSpreadElement) {
2456
- let unionOfElements = getUnionType(elementTypes);
2457
- return languageVersion >= ScriptTarget.ES6 ? createIterableType(unionOfElements) : createArrayType(unionOfElements);
2458
- }
2459
2452
// If the pattern has at least one element, and no rest element, then it should imply a tuple type.
2460
- return createTupleType(elementTypes);
2453
+ let elementTypes = map(elements, e => e.kind === SyntaxKind.OmittedExpression ? anyType : getTypeFromBindingElement(e));
2454
+ let result = createTupleType(elementTypes);
2455
+ if (includePatternInType) {
2456
+ result = clone(result);
2457
+ result.pattern = pattern;
2458
+ }
2459
+ return result;
2461
2460
}
2462
2461
2463
2462
// Return the type implied by a binding pattern. This is the type implied purely by the binding pattern itself
@@ -2467,10 +2466,10 @@ namespace ts {
2467
2466
// used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring
2468
2467
// parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of
2469
2468
// the parameter.
2470
- function getTypeFromBindingPattern(pattern: BindingPattern): Type {
2469
+ function getTypeFromBindingPattern(pattern: BindingPattern, includePatternInType?: boolean ): Type {
2471
2470
return pattern.kind === SyntaxKind.ObjectBindingPattern
2472
- ? getTypeFromObjectBindingPattern(pattern)
2473
- : getTypeFromArrayBindingPattern(pattern);
2471
+ ? getTypeFromObjectBindingPattern(pattern, includePatternInType )
2472
+ : getTypeFromArrayBindingPattern(pattern, includePatternInType );
2474
2473
}
2475
2474
2476
2475
// Return the type associated with a variable, parameter, or property declaration. In the simple case this is the type
@@ -6606,18 +6605,12 @@ namespace ts {
6606
6605
}
6607
6606
}
6608
6607
if (isBindingPattern(declaration.name)) {
6609
- return createImpliedType( getTypeFromBindingPattern(<BindingPattern>declaration.name) );
6608
+ return getTypeFromBindingPattern(<BindingPattern>declaration.name, /*includePatternInType*/ true );
6610
6609
}
6611
6610
}
6612
6611
return undefined;
6613
6612
}
6614
6613
6615
- function createImpliedType(type: Type): Type {
6616
- var result = clone(type);
6617
- result.flags |= TypeFlags.ImpliedType;
6618
- return result;
6619
- }
6620
-
6621
6614
function getContextualTypeForReturnExpression(node: Expression): Type {
6622
6615
let func = getContainingFunction(node);
6623
6616
if (func && !func.asteriskToken) {
@@ -7044,17 +7037,28 @@ namespace ts {
7044
7037
// If array literal is actually a destructuring pattern, mark it as an implied type. We do this such
7045
7038
// that we get the same behavior for "var [x, y] = []" and "[x, y] = []".
7046
7039
if (inDestructuringPattern && elementTypes.length) {
7047
- return createImpliedType(createTupleType(elementTypes));
7040
+ let type = clone(createTupleType(elementTypes));
7041
+ type.pattern = node;
7042
+ return type;
7048
7043
}
7049
7044
let contextualType = getContextualType(node);
7050
- let contextualTupleLikeType = contextualType && contextualTypeIsTupleLikeType(contextualType) ? contextualType : undefined;
7051
- if (contextualTupleLikeType) {
7052
- // If array literal is contextually typed by the implied type of a binding pattern, pad the resulting
7053
- // tuple type with elements from the binding tuple type to make the lengths equal.
7054
- if (contextualTupleLikeType.flags & TypeFlags.Tuple && contextualTupleLikeType.flags & TypeFlags.ImpliedType) {
7055
- let contextualElementTypes = (<TupleType>contextualTupleLikeType).elementTypes;
7056
- for (let i = elementTypes.length; i < contextualElementTypes.length; i++) {
7057
- elementTypes.push(contextualElementTypes[i]);
7045
+ if (contextualType && contextualTypeIsTupleLikeType(contextualType)) {
7046
+ let pattern = contextualType.pattern;
7047
+ // If array literal is contextually typed by a binding pattern or an assignment pattern,
7048
+ // pad the resulting tuple type to make the lengths equal.
7049
+ if (pattern && pattern.kind === SyntaxKind.ArrayBindingPattern) {
7050
+ let bindingElements = (<BindingPattern>pattern).elements;
7051
+ for (let i = elementTypes.length; i < bindingElements.length; i++) {
7052
+ let hasDefaultValue = bindingElements[i].initializer;
7053
+ elementTypes.push(hasDefaultValue ? (<TupleType>contextualType).elementTypes[i] : undefinedType);
7054
+ }
7055
+ }
7056
+ else if (pattern && pattern.kind === SyntaxKind.ArrayLiteralExpression) {
7057
+ let assignmentElements = (<ArrayLiteralExpression>pattern).elements;
7058
+ for (let i = elementTypes.length; i < assignmentElements.length; i++) {
7059
+ let hasDefaultValue = assignmentElements[i].kind === SyntaxKind.BinaryExpression &&
7060
+ (<BinaryExpression>assignmentElements[i]).operatorToken.kind === SyntaxKind.EqualsToken;
7061
+ elementTypes.push(hasDefaultValue ? (<TupleType>contextualType).elementTypes[i] : undefinedType);
7058
7062
}
7059
7063
}
7060
7064
if (elementTypes.length) {
@@ -7129,6 +7133,8 @@ namespace ts {
7129
7133
let propertiesTable: SymbolTable = {};
7130
7134
let propertiesArray: Symbol[] = [];
7131
7135
let contextualType = getContextualType(node);
7136
+ let contextualTypeHasPattern = contextualType && contextualType.pattern &&
7137
+ contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern;
7132
7138
let typeFlags: TypeFlags = 0;
7133
7139
7134
7140
for (let memberDecl of node.properties) {
@@ -7151,7 +7157,7 @@ namespace ts {
7151
7157
let prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
7152
7158
// If object literal is contextually typed by the implied type of a binding pattern, and if the
7153
7159
// binding pattern specifies a default value for the property, make the property optional.
7154
- if (contextualType && contextualType.flags & TypeFlags.ImpliedType ) {
7160
+ if (contextualTypeHasPattern ) {
7155
7161
let impliedProp = getPropertyOfType(contextualType, member.name);
7156
7162
if (impliedProp) {
7157
7163
prop.flags |= impliedProp.flags & SymbolFlags.Optional;
@@ -7185,7 +7191,7 @@ namespace ts {
7185
7191
7186
7192
// If object literal is contextually typed by the implied type of a binding pattern, augment the result
7187
7193
// type with those properties for which the binding pattern specifies a default value.
7188
- if (contextualType && contextualType.flags & TypeFlags.ImpliedType ) {
7194
+ if (contextualTypeHasPattern ) {
7189
7195
for (let prop of getPropertiesOfType(contextualType)) {
7190
7196
if (prop.flags & SymbolFlags.Optional && !hasProperty(propertiesTable, prop.name)) {
7191
7197
propertiesTable[prop.name] = prop;
0 commit comments