@@ -7001,6 +7001,11 @@ namespace ts {
70017001 return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false);
70027002 }
70037003
7004+ function hasDefaultValue(node: BindingElement | Expression): boolean {
7005+ return (node.kind === SyntaxKind.BindingElement && !!(<BindingElement>node).initializer) ||
7006+ (node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.EqualsToken);
7007+ }
7008+
70047009 function checkArrayLiteral(node: ArrayLiteralExpression, contextualMapper?: TypeMapper): Type {
70057010 let elements = node.elements;
70067011 let hasSpreadElement = false;
@@ -7044,21 +7049,12 @@ namespace ts {
70447049 let contextualType = getContextualType(node);
70457050 if (contextualType && contextualTypeIsTupleLikeType(contextualType)) {
70467051 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);
7052+ // If array literal is contextually typed by a binding pattern or an assignment pattern, pad the
7053+ // resulting tuple type to make the lengths equal.
7054+ if (pattern && (pattern.kind === SyntaxKind.ArrayBindingPattern || pattern.kind === SyntaxKind.ArrayLiteralExpression)) {
7055+ let patternElements = (<BindingPattern | ArrayLiteralExpression>pattern).elements;
7056+ for (let i = elementTypes.length; i < patternElements.length; i++) {
7057+ elementTypes.push(hasDefaultValue(patternElements[i]) ? (<TupleType>contextualType).elementTypes[i] : undefinedType);
70627058 }
70637059 }
70647060 if (elementTypes.length) {
@@ -7134,7 +7130,8 @@ namespace ts {
71347130 let propertiesArray: Symbol[] = [];
71357131 let contextualType = getContextualType(node);
71367132 let contextualTypeHasPattern = contextualType && contextualType.pattern &&
7137- contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern;
7133+ (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
7134+ let inDestructuringPattern = isAssignmentTarget(node);
71387135 let typeFlags: TypeFlags = 0;
71397136
71407137 for (let memberDecl of node.properties) {
@@ -7155,13 +7152,24 @@ namespace ts {
71557152 }
71567153 typeFlags |= type.flags;
71577154 let prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
7158- // If object literal is contextually typed by the implied type of a binding pattern, and if the
7159- // binding pattern specifies a default value for the property, make the property optional.
7160- if (contextualTypeHasPattern) {
7155+ if (inDestructuringPattern) {
7156+ // If object literal is an assignment pattern and if the assignment pattern specifies a default value
7157+ // for the property, make the property optional.
7158+ if (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue((<PropertyAssignment>memberDecl).initializer)) {
7159+ prop.flags |= SymbolFlags.Optional;
7160+ }
7161+ }
7162+ else if (contextualTypeHasPattern) {
7163+ // If object literal is contextually typed by the implied type of a binding pattern, and if the
7164+ // binding pattern specifies a default value for the property, make the property optional.
71617165 let impliedProp = getPropertyOfType(contextualType, member.name);
71627166 if (impliedProp) {
71637167 prop.flags |= impliedProp.flags & SymbolFlags.Optional;
71647168 }
7169+ else if (!compilerOptions.suppressExcessPropertyErrors) {
7170+ error(memberDecl.name, Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
7171+ symbolToString(member), typeToString(contextualType));
7172+ }
71657173 }
71667174 prop.declarations = member.declarations;
71677175 prop.parent = member.parent;
@@ -7205,6 +7213,9 @@ namespace ts {
72057213 let result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
72067214 let freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshObjectLiteral;
72077215 result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags);
7216+ if (inDestructuringPattern) {
7217+ result.pattern = node;
7218+ }
72087219 return result;
72097220
72107221 function getIndexType(kind: IndexKind) {
0 commit comments