@@ -7001,6 +7001,11 @@ namespace ts {
7001
7001
return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false);
7002
7002
}
7003
7003
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
+
7004
7009
function checkArrayLiteral(node: ArrayLiteralExpression, contextualMapper?: TypeMapper): Type {
7005
7010
let elements = node.elements;
7006
7011
let hasSpreadElement = false;
@@ -7044,21 +7049,12 @@ namespace ts {
7044
7049
let contextualType = getContextualType(node);
7045
7050
if (contextualType && contextualTypeIsTupleLikeType(contextualType)) {
7046
7051
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);
7062
7058
}
7063
7059
}
7064
7060
if (elementTypes.length) {
@@ -7134,7 +7130,8 @@ namespace ts {
7134
7130
let propertiesArray: Symbol[] = [];
7135
7131
let contextualType = getContextualType(node);
7136
7132
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);
7138
7135
let typeFlags: TypeFlags = 0;
7139
7136
7140
7137
for (let memberDecl of node.properties) {
@@ -7155,13 +7152,24 @@ namespace ts {
7155
7152
}
7156
7153
typeFlags |= type.flags;
7157
7154
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.
7161
7165
let impliedProp = getPropertyOfType(contextualType, member.name);
7162
7166
if (impliedProp) {
7163
7167
prop.flags |= impliedProp.flags & SymbolFlags.Optional;
7164
7168
}
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
+ }
7165
7173
}
7166
7174
prop.declarations = member.declarations;
7167
7175
prop.parent = member.parent;
@@ -7205,6 +7213,9 @@ namespace ts {
7205
7213
let result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
7206
7214
let freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshObjectLiteral;
7207
7215
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags);
7216
+ if (inDestructuringPattern) {
7217
+ result.pattern = node;
7218
+ }
7208
7219
return result;
7209
7220
7210
7221
function getIndexType(kind: IndexKind) {
0 commit comments