Skip to content

Commit 9d274f6

Browse files
committed
Improve excess property checking for intersections
Still a draft, the implementation needs improvement
1 parent 772bee5 commit 9d274f6

15 files changed

+219
-57
lines changed

src/compiler/checker.ts

+27-27
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//// [excessPropertyCheckWithNestedArrayIntersection.ts]
2+
interface ValueOnlyFields {
3+
fields: Array<{
4+
value: number | null;
5+
}>;
6+
}
7+
interface ValueAndKeyFields {
8+
fields: Array<{
9+
key: string | null;
10+
value: number | null;
11+
}>;
12+
}
13+
interface BugRepro {
14+
dataType: ValueAndKeyFields & ValueOnlyFields;
15+
}
16+
const repro: BugRepro = {
17+
dataType: {
18+
fields: [{
19+
key: 'bla', // should be OK: Not excess
20+
value: null,
21+
}],
22+
}
23+
}
24+
25+
26+
//// [excessPropertyCheckWithNestedArrayIntersection.js]
27+
var repro = {
28+
dataType: {
29+
fields: [{
30+
key: 'bla',
31+
value: null
32+
}]
33+
}
34+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
=== tests/cases/compiler/excessPropertyCheckWithNestedArrayIntersection.ts ===
2+
interface ValueOnlyFields {
3+
>ValueOnlyFields : Symbol(ValueOnlyFields, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 0, 0))
4+
5+
fields: Array<{
6+
>fields : Symbol(ValueOnlyFields.fields, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 0, 27))
7+
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
8+
9+
value: number | null;
10+
>value : Symbol(value, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 1, 19))
11+
12+
}>;
13+
}
14+
interface ValueAndKeyFields {
15+
>ValueAndKeyFields : Symbol(ValueAndKeyFields, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 4, 1))
16+
17+
fields: Array<{
18+
>fields : Symbol(ValueAndKeyFields.fields, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 5, 29))
19+
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
20+
21+
key: string | null;
22+
>key : Symbol(key, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 6, 19))
23+
24+
value: number | null;
25+
>value : Symbol(value, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 7, 27))
26+
27+
}>;
28+
}
29+
interface BugRepro {
30+
>BugRepro : Symbol(BugRepro, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 10, 1))
31+
32+
dataType: ValueAndKeyFields & ValueOnlyFields;
33+
>dataType : Symbol(BugRepro.dataType, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 11, 20))
34+
>ValueAndKeyFields : Symbol(ValueAndKeyFields, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 4, 1))
35+
>ValueOnlyFields : Symbol(ValueOnlyFields, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 0, 0))
36+
}
37+
const repro: BugRepro = {
38+
>repro : Symbol(repro, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 14, 5))
39+
>BugRepro : Symbol(BugRepro, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 10, 1))
40+
41+
dataType: {
42+
>dataType : Symbol(dataType, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 14, 25))
43+
44+
fields: [{
45+
>fields : Symbol(fields, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 15, 13))
46+
47+
key: 'bla', // should be OK: Not excess
48+
>key : Symbol(key, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 16, 14))
49+
50+
value: null,
51+
>value : Symbol(value, Decl(excessPropertyCheckWithNestedArrayIntersection.ts, 17, 17))
52+
53+
}],
54+
}
55+
}
56+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
=== tests/cases/compiler/excessPropertyCheckWithNestedArrayIntersection.ts ===
2+
interface ValueOnlyFields {
3+
fields: Array<{
4+
>fields : { value: number; }[]
5+
6+
value: number | null;
7+
>value : number
8+
>null : null
9+
10+
}>;
11+
}
12+
interface ValueAndKeyFields {
13+
fields: Array<{
14+
>fields : { key: string; value: number; }[]
15+
16+
key: string | null;
17+
>key : string
18+
>null : null
19+
20+
value: number | null;
21+
>value : number
22+
>null : null
23+
24+
}>;
25+
}
26+
interface BugRepro {
27+
dataType: ValueAndKeyFields & ValueOnlyFields;
28+
>dataType : ValueAndKeyFields & ValueOnlyFields
29+
}
30+
const repro: BugRepro = {
31+
>repro : BugRepro
32+
>{ dataType: { fields: [{ key: 'bla', // should be OK: Not excess value: null, }], }} : { dataType: { fields: { key: string; value: null; }[]; }; }
33+
34+
dataType: {
35+
>dataType : { fields: { key: string; value: null; }[]; }
36+
>{ fields: [{ key: 'bla', // should be OK: Not excess value: null, }], } : { fields: { key: string; value: null; }[]; }
37+
38+
fields: [{
39+
>fields : { key: string; value: null; }[]
40+
>[{ key: 'bla', // should be OK: Not excess value: null, }] : { key: string; value: null; }[]
41+
>{ key: 'bla', // should be OK: Not excess value: null, } : { key: string; value: null; }
42+
43+
key: 'bla', // should be OK: Not excess
44+
>key : string
45+
>'bla' : "bla"
46+
47+
value: null,
48+
>value : null
49+
>null : null
50+
51+
}],
52+
}
53+
}
54+

tests/baselines/reference/excessPropertyChecksWithNestedIntersections.errors.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts(70,50): erro
4747
~
4848
!!! error TS2322: Type 'number' is not assignable to type 'string'.
4949
!!! related TS6500 tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts:4:5: The expected type comes from property 'x' which is declared here on type 'A'
50-
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
50+
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // error - y does not exist in type A
5151
~~~~
5252
!!! error TS2322: Type '{ x: string; y: number; }' is not assignable to type 'A'.
5353
!!! error TS2322: Object literal may only specify known properties, and 'y' does not exist in type 'A'.

tests/baselines/reference/excessPropertyChecksWithNestedIntersections.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let c: B = { a: { x: 'hello', y: 2 } }; // error - y does not exist in type A
2121

2222
let d: D = { a: { x: 'hello' }, c: 5 }; // ok
2323
let e: D = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatible
24-
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
24+
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // error - y does not exist in type A
2525

2626
// https://github.com/Microsoft/TypeScript/issues/18075
2727

@@ -80,7 +80,7 @@ var b = { a: { x: 2 } }; // error - types of property x are incompatible
8080
var c = { a: { x: 'hello', y: 2 } }; // error - y does not exist in type A
8181
var d = { a: { x: 'hello' }, c: 5 }; // ok
8282
var e = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatible
83-
var f = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
83+
var f = { a: { x: 'hello', y: 2 }, c: 5 }; // error - y does not exist in type A
8484
exports.photo = {
8585
id: 1,
8686
url: '',

tests/baselines/reference/excessPropertyChecksWithNestedIntersections.symbols

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ let e: D = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatibl
6161
>x : Symbol(x, Decl(excessPropertyChecksWithNestedIntersections.ts, 21, 17))
6262
>c : Symbol(c, Decl(excessPropertyChecksWithNestedIntersections.ts, 21, 25))
6363

64-
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
64+
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // error - y does not exist in type A
6565
>f : Symbol(f, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 3))
6666
>D : Symbol(D, Decl(excessPropertyChecksWithNestedIntersections.ts, 12, 1))
6767
>a : Symbol(a, Decl(excessPropertyChecksWithNestedIntersections.ts, 22, 12))

tests/baselines/reference/excessPropertyChecksWithNestedIntersections.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ let e: D = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatibl
6565
>c : number
6666
>5 : 5
6767

68-
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
68+
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // error - y does not exist in type A
6969
>f : D
7070
>{ a: { x: 'hello', y: 2 }, c: 5 } : { a: { x: string; y: number; }; c: number; }
7171
>a : { x: string; y: number; }

tests/baselines/reference/weakType.errors.txt

+6-10
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@ tests/cases/compiler/weakType.ts(18,13): error TS2559: Type '12' has no properti
55
tests/cases/compiler/weakType.ts(19,13): error TS2559: Type '"completely wrong"' has no properties in common with type 'Settings'.
66
tests/cases/compiler/weakType.ts(20,13): error TS2559: Type 'false' has no properties in common with type 'Settings'.
77
tests/cases/compiler/weakType.ts(37,18): error TS2559: Type '{ error?: number; }' has no properties in common with type 'ChangeOptions'.
8-
tests/cases/compiler/weakType.ts(62,5): error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'.
9-
Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak'.
10-
Types of property 'properties' are incompatible.
11-
Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'.
8+
tests/cases/compiler/weakType.ts(62,5): error TS2326: Types of property 'properties' are incompatible.
9+
Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'.
1210

1311

1412
==== tests/cases/compiler/weakType.ts (8 errors) ====
@@ -85,16 +83,14 @@ tests/cases/compiler/weakType.ts(62,5): error TS2322: Type '{ properties: { wron
8583
b?: number
8684
}
8785
}
88-
declare let unknown: {
86+
declare let propertiesWrong: {
8987
properties: {
9088
wrong: string
9189
}
9290
}
93-
let weak: Weak & Spoiler = unknown
91+
let weak: Weak & Spoiler = propertiesWrong
9492
~~~~
95-
!!! error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak & Spoiler'.
96-
!!! error TS2322: Type '{ properties: { wrong: string; }; }' is not assignable to type 'Weak'.
97-
!!! error TS2322: Types of property 'properties' are incompatible.
98-
!!! error TS2322: Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'.
93+
!!! error TS2326: Types of property 'properties' are incompatible.
94+
!!! error TS2326: Type '{ wrong: string; }' has no properties in common with type '{ b?: number; }'.
9995

10096

tests/baselines/reference/weakType.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ type Weak = {
5555
b?: number
5656
}
5757
}
58-
declare let unknown: {
58+
declare let propertiesWrong: {
5959
properties: {
6060
wrong: string
6161
}
6262
}
63-
let weak: Weak & Spoiler = unknown
63+
let weak: Weak & Spoiler = propertiesWrong
6464

6565

6666

@@ -89,4 +89,4 @@ var K = /** @class */ (function () {
8989
return K;
9090
}());
9191
var ctor = K;
92-
var weak = unknown;
92+
var weak = propertiesWrong;

tests/baselines/reference/weakType.symbols

+5-5
Original file line numberDiff line numberDiff line change
@@ -144,20 +144,20 @@ type Weak = {
144144
>b : Symbol(b, Decl(weakType.ts, 52, 18))
145145
}
146146
}
147-
declare let unknown: {
148-
>unknown : Symbol(unknown, Decl(weakType.ts, 56, 11))
147+
declare let propertiesWrong: {
148+
>propertiesWrong : Symbol(propertiesWrong, Decl(weakType.ts, 56, 11))
149149

150150
properties: {
151-
>properties : Symbol(properties, Decl(weakType.ts, 56, 22))
151+
>properties : Symbol(properties, Decl(weakType.ts, 56, 30))
152152

153153
wrong: string
154154
>wrong : Symbol(wrong, Decl(weakType.ts, 57, 17))
155155
}
156156
}
157-
let weak: Weak & Spoiler = unknown
157+
let weak: Weak & Spoiler = propertiesWrong
158158
>weak : Symbol(weak, Decl(weakType.ts, 61, 3))
159159
>Weak : Symbol(Weak, Decl(weakType.ts, 49, 32))
160160
>Spoiler : Symbol(Spoiler, Decl(weakType.ts, 47, 18))
161-
>unknown : Symbol(unknown, Decl(weakType.ts, 56, 11))
161+
>propertiesWrong : Symbol(propertiesWrong, Decl(weakType.ts, 56, 11))
162162

163163

tests/baselines/reference/weakType.types

+4-4
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ type Weak = {
147147
>b : number
148148
}
149149
}
150-
declare let unknown: {
151-
>unknown : { properties: { wrong: string; }; }
150+
declare let propertiesWrong: {
151+
>propertiesWrong : { properties: { wrong: string; }; }
152152

153153
properties: {
154154
>properties : { wrong: string; }
@@ -157,8 +157,8 @@ declare let unknown: {
157157
>wrong : string
158158
}
159159
}
160-
let weak: Weak & Spoiler = unknown
160+
let weak: Weak & Spoiler = propertiesWrong
161161
>weak : Weak & Spoiler
162-
>unknown : { properties: { wrong: string; }; }
162+
>propertiesWrong : { properties: { wrong: string; }; }
163163

164164

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
interface ValueOnlyFields {
2+
fields: Array<{
3+
value: number | null;
4+
}>;
5+
}
6+
interface ValueAndKeyFields {
7+
fields: Array<{
8+
key: string | null;
9+
value: number | null;
10+
}>;
11+
}
12+
interface BugRepro {
13+
dataType: ValueAndKeyFields & ValueOnlyFields;
14+
}
15+
const repro: BugRepro = {
16+
dataType: {
17+
fields: [{
18+
key: 'bla', // should be OK: Not excess
19+
value: null,
20+
}],
21+
}
22+
}

tests/cases/compiler/excessPropertyChecksWithNestedIntersections.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ let c: B = { a: { x: 'hello', y: 2 } }; // error - y does not exist in type A
2020

2121
let d: D = { a: { x: 'hello' }, c: 5 }; // ok
2222
let e: D = { a: { x: 2 }, c: 5 }; // error - types of property x are incompatible
23-
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // should be an error
23+
let f: D = { a: { x: 'hello', y: 2 }, c: 5 }; // error - y does not exist in type A
2424

2525
// https://github.com/Microsoft/TypeScript/issues/18075
2626

tests/cases/compiler/weakType.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ type Weak = {
5454
b?: number
5555
}
5656
}
57-
declare let unknown: {
57+
declare let propertiesWrong: {
5858
properties: {
5959
wrong: string
6060
}
6161
}
62-
let weak: Weak & Spoiler = unknown
62+
let weak: Weak & Spoiler = propertiesWrong
6363

0 commit comments

Comments
 (0)