Skip to content

Commit 72723e9

Browse files
committed
do not report 'excess property error' if object literal pattern contains computed properties
1 parent 572db9c commit 72723e9

File tree

4 files changed

+15
-77
lines changed

4 files changed

+15
-77
lines changed

src/compiler/checker.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -2500,10 +2500,12 @@ namespace ts {
25002500
// Return the type implied by an object binding pattern
25012501
function getTypeFromObjectBindingPattern(pattern: BindingPattern, includePatternInType: boolean): Type {
25022502
const members: SymbolTable = {};
2503+
let hasComputedProperties = false;
25032504
forEach(pattern.elements, e => {
25042505
const name = e.propertyName || <Identifier>e.name;
25052506
if (isComputedNonLiteralName(name)) {
25062507
// do not include computed properties in the implied type
2508+
hasComputedProperties = true;
25072509
return;
25082510
}
25092511

@@ -2518,6 +2520,9 @@ namespace ts {
25182520
if (includePatternInType) {
25192521
result.pattern = pattern;
25202522
}
2523+
if (hasComputedProperties) {
2524+
result.flags |= TypeFlags.ObjectLiteralPatternWithComputedProperties;
2525+
}
25212526
return result;
25222527
}
25232528

@@ -5010,7 +5015,7 @@ namespace ts {
50105015
}
50115016

50125017
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
5013-
if (someConstituentTypeHasKind(target, TypeFlags.ObjectType)) {
5018+
if (!(target.flags & TypeFlags.ObjectLiteralPatternWithComputedProperties) && someConstituentTypeHasKind(target, TypeFlags.ObjectType)) {
50145019
for (const prop of getPropertiesOfObjectType(source)) {
50155020
if (!isKnownProperty(target, prop.name)) {
50165021
if (reportErrors) {
@@ -7428,6 +7433,7 @@ namespace ts {
74287433
(contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
74297434
let typeFlags: TypeFlags = 0;
74307435

7436+
let patternWithComputedProperties = false;
74317437
for (const memberDecl of node.properties) {
74327438
let member = memberDecl.symbol;
74337439
if (memberDecl.kind === SyntaxKind.PropertyAssignment ||
@@ -7455,8 +7461,11 @@ namespace ts {
74557461
if (isOptional) {
74567462
prop.flags |= SymbolFlags.Optional;
74577463
}
7464+
if (hasDynamicName(memberDecl)) {
7465+
patternWithComputedProperties = true;
7466+
}
74587467
}
7459-
else if (contextualTypeHasPattern) {
7468+
else if (contextualTypeHasPattern && !(contextualType.flags & TypeFlags.ObjectLiteralPatternWithComputedProperties)) {
74607469
// If object literal is contextually typed by the implied type of a binding pattern, and if the
74617470
// binding pattern specifies a default value for the property, make the property optional.
74627471
const impliedProp = getPropertyOfType(contextualType, member.name);
@@ -7513,7 +7522,7 @@ namespace ts {
75137522
const numberIndexType = getIndexType(IndexKind.Number);
75147523
const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
75157524
const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshObjectLiteral;
7516-
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags);
7525+
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags) | (patternWithComputedProperties ? TypeFlags.ObjectLiteralPatternWithComputedProperties : 0);
75177526
if (inDestructuringPattern) {
75187527
result.pattern = node;
75197528
}

src/compiler/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1822,6 +1822,7 @@ namespace ts {
18221822
ContainsAnyFunctionType = 0x00800000, // Type is or contains object literal type
18231823
ESSymbol = 0x01000000, // Type of symbol primitive introduced in ES6
18241824
ThisType = 0x02000000, // This type
1825+
ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties
18251826

18261827
/* @internal */
18271828
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,21 @@
1-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(3,21): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
2-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(8,25): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
3-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(10,25): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
4-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(11,28): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
51
tests/cases/compiler/computedPropertiesInDestructuring1.ts(20,8): error TS2349: Cannot invoke an expression whose type lacks a call signature.
6-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(20,27): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
72
tests/cases/compiler/computedPropertiesInDestructuring1.ts(21,12): error TS2339: Property 'toExponential' does not exist on type 'string'.
8-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(21,41): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
9-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(24,18): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
10-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(28,22): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
11-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(30,21): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
12-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(31,24): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
133
tests/cases/compiler/computedPropertiesInDestructuring1.ts(33,4): error TS2349: Cannot invoke an expression whose type lacks a call signature.
14-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(33,23): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
154
tests/cases/compiler/computedPropertiesInDestructuring1.ts(34,5): error TS2365: Operator '+' cannot be applied to types 'number' and '{}'.
16-
tests/cases/compiler/computedPropertiesInDestructuring1.ts(34,26): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
175

186

19-
==== tests/cases/compiler/computedPropertiesInDestructuring1.ts (16 errors) ====
7+
==== tests/cases/compiler/computedPropertiesInDestructuring1.ts (4 errors) ====
208
// destructuring in variable declarations
219
let foo = "bar";
2210
let {[foo]: bar} = {bar: "bar"};
23-
~~~
24-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
2511

2612
let {["bar"]: bar2} = {bar: "bar"};
2713

2814
let foo2 = () => "bar";
2915
let {[foo2()]: bar3} = {bar: "bar"};
30-
~~~
31-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
3216

3317
let [{[foo]: bar4}] = [{bar: "bar"}];
34-
~~~
35-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
3618
let [{[foo2()]: bar5}] = [{bar: "bar"}];
37-
~~~
38-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
3919

4020
function f1({["bar"]: x}: { bar: number }) {}
4121
function f2({[foo]: x}: { bar: number }) {}
@@ -47,42 +27,26 @@ tests/cases/compiler/computedPropertiesInDestructuring1.ts(34,26): error TS2353:
4727
let [{[foo()]: bar6}] = [{bar: "bar"}];
4828
~~~~~
4929
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature.
50-
~~~
51-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
5230
let [{[foo.toExponential()]: bar7}] = [{bar: "bar"}];
5331
~~~~~~~~~~~~~
5432
!!! error TS2339: Property 'toExponential' does not exist on type 'string'.
55-
~~~
56-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
5733

5834
// destructuring assignment
5935
({[foo]: bar} = {bar: "bar"});
60-
~~~
61-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
6236

6337
({["bar"]: bar2} = {bar: "bar"});
6438

6539
({[foo2()]: bar3} = {bar: "bar"});
66-
~~~
67-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
6840

6941
[{[foo]: bar4}] = [{bar: "bar"}];
70-
~~~
71-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
7242
[{[foo2()]: bar5}] = [{bar: "bar"}];
73-
~~~
74-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
7543

7644
[{[foo()]: bar4}] = [{bar: "bar"}];
7745
~~~~~
7846
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature.
79-
~~~
80-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
8147
[{[(1 + {})]: bar4}] = [{bar: "bar"}];
8248
~~~~~~
8349
!!! error TS2365: Operator '+' cannot be applied to types 'number' and '{}'.
84-
~~~
85-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
8650

8751

8852

Original file line numberDiff line numberDiff line change
@@ -1,42 +1,22 @@
1-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(3,21): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
2-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(9,25): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
3-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(11,25): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
4-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(12,28): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
51
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(21,8): error TS2349: Cannot invoke an expression whose type lacks a call signature.
6-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(21,27): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
72
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(22,12): error TS2339: Property 'toExponential' does not exist on type 'string'.
8-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(22,41): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
9-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(25,18): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
10-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(29,22): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
11-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(31,21): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
12-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(32,24): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
133
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(34,4): error TS2349: Cannot invoke an expression whose type lacks a call signature.
14-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(34,23): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
154
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(35,5): error TS2365: Operator '+' cannot be applied to types 'number' and '{}'.
16-
tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(35,26): error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
175

186

19-
==== tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts (16 errors) ====
7+
==== tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts (4 errors) ====
208
// destructuring in variable declarations
219
let foo = "bar";
2210
let {[foo]: bar} = {bar: "bar"};
23-
~~~
24-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
2511

2612
let {["bar"]: bar2} = {bar: "bar"};
2713
let {[11]: bar2_1} = {11: "bar"};
2814

2915
let foo2 = () => "bar";
3016
let {[foo2()]: bar3} = {bar: "bar"};
31-
~~~
32-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
3317

3418
let [{[foo]: bar4}] = [{bar: "bar"}];
35-
~~~
36-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
3719
let [{[foo2()]: bar5}] = [{bar: "bar"}];
38-
~~~
39-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
4020

4121
function f1({["bar"]: x}: { bar: number }) {}
4222
function f2({[foo]: x}: { bar: number }) {}
@@ -48,40 +28,24 @@ tests/cases/compiler/computedPropertiesInDestructuring1_ES6.ts(35,26): error TS2
4828
let [{[foo()]: bar6}] = [{bar: "bar"}];
4929
~~~~~
5030
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature.
51-
~~~
52-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
5331
let [{[foo.toExponential()]: bar7}] = [{bar: "bar"}];
5432
~~~~~~~~~~~~~
5533
!!! error TS2339: Property 'toExponential' does not exist on type 'string'.
56-
~~~
57-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
5834

5935
// destructuring assignment
6036
({[foo]: bar} = {bar: "bar"});
61-
~~~
62-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
6337

6438
({["bar"]: bar2} = {bar: "bar"});
6539

6640
({[foo2()]: bar3} = {bar: "bar"});
67-
~~~
68-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
6941

7042
[{[foo]: bar4}] = [{bar: "bar"}];
71-
~~~
72-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
7343
[{[foo2()]: bar5}] = [{bar: "bar"}];
74-
~~~
75-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
7644

7745
[{[foo()]: bar4}] = [{bar: "bar"}];
7846
~~~~~
7947
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature.
80-
~~~
81-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
8248
[{[(1 + {})]: bar4}] = [{bar: "bar"}];
8349
~~~~~~
8450
!!! error TS2365: Operator '+' cannot be applied to types 'number' and '{}'.
85-
~~~
86-
!!! error TS2353: Object literal may only specify known properties, and 'bar' does not exist in type '{}'.
8751

0 commit comments

Comments
 (0)