Skip to content

Commit 97610a8

Browse files
authored
1 parent 1cd5309 commit 97610a8

File tree

5 files changed

+362
-17
lines changed

5 files changed

+362
-17
lines changed

src/compiler/checker.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27885,24 +27885,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2788527885
for (const type of types) {
2788627886
if (type.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive)) {
2788727887
const discriminant = getTypeOfPropertyOfType(type, name);
27888-
if (discriminant) {
27889-
if (!isLiteralType(discriminant)) {
27890-
return undefined;
27891-
}
27892-
let duplicate = false;
27893-
forEachType(discriminant, t => {
27894-
const id = getTypeId(getRegularTypeOfLiteralType(t));
27895-
const existing = map.get(id);
27896-
if (!existing) {
27897-
map.set(id, type);
27898-
}
27899-
else if (existing !== unknownType) {
27900-
map.set(id, unknownType);
27901-
duplicate = true;
27902-
}
27903-
});
27904-
if (!duplicate) count++;
27888+
if (!discriminant || !isLiteralType(discriminant)) {
27889+
return undefined;
2790527890
}
27891+
let duplicate = false;
27892+
forEachType(discriminant, t => {
27893+
const id = getTypeId(getRegularTypeOfLiteralType(t));
27894+
const existing = map.get(id);
27895+
if (!existing) {
27896+
map.set(id, type);
27897+
}
27898+
else if (existing !== unknownType) {
27899+
map.set(id, unknownType);
27900+
duplicate = true;
27901+
}
27902+
});
27903+
if (!duplicate) count++;
2790627904
}
2790727905
}
2790827906
return count >= 10 && count * 2 >= types.length ? map : undefined;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
missingDiscriminants2.ts(30,23): error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.
2+
missingDiscriminants2.ts(31,34): error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.
3+
4+
5+
==== missingDiscriminants2.ts (2 errors) ====
6+
// https://github.com/microsoft/typescript-go/issues/1020
7+
8+
type Thing =
9+
| { str: "a", num: 0 }
10+
| { str: "b" }
11+
| { str: "c" }
12+
| { str: "d" }
13+
| { str: "e" }
14+
| { str: "f" }
15+
| { str: "g" }
16+
| { str: "h" }
17+
| { str: "i" }
18+
| { str: "j" }
19+
| { str: "k" }
20+
| { str: "l" }
21+
| { str: "m" }
22+
| { str: "n" }
23+
| { str: "o" }
24+
| { num: 1 }
25+
26+
const thing1: Thing = { str: "a", num: 0 }
27+
const thing2: Thing = { str: "b", num: 1 } // Shouldn't be error
28+
const thing3: Thing = { num: 1, str: "b" } // Shouldn't be error
29+
30+
type Item =
31+
| { kind: "a", subkind: 0, value: string }
32+
| { kind: "a", subkind: 1, value: number }
33+
| { kind: "b" }
34+
35+
const item1: Item = { subkind: 1, kind: "b" } // Error, type "b" not assignable to type "a"
36+
~~~~~~~
37+
!!! error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.
38+
const item2: Item = { kind: "b", subkind: 1 } // Error, 'subkind' isn't a known property
39+
~~~~~~~
40+
!!! error TS2353: Object literal may only specify known properties, and 'subkind' does not exist in type '{ kind: "b"; }'.
41+
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//// [tests/cases/compiler/missingDiscriminants2.ts] ////
2+
3+
=== missingDiscriminants2.ts ===
4+
// https://github.com/microsoft/typescript-go/issues/1020
5+
6+
type Thing =
7+
>Thing : Symbol(Thing, Decl(missingDiscriminants2.ts, 0, 0))
8+
9+
| { str: "a", num: 0 }
10+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 3, 5))
11+
>num : Symbol(num, Decl(missingDiscriminants2.ts, 3, 15))
12+
13+
| { str: "b" }
14+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 4, 5))
15+
16+
| { str: "c" }
17+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 5, 5))
18+
19+
| { str: "d" }
20+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 6, 5))
21+
22+
| { str: "e" }
23+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 7, 5))
24+
25+
| { str: "f" }
26+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 8, 5))
27+
28+
| { str: "g" }
29+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 9, 5))
30+
31+
| { str: "h" }
32+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 10, 5))
33+
34+
| { str: "i" }
35+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 11, 5))
36+
37+
| { str: "j" }
38+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 12, 5))
39+
40+
| { str: "k" }
41+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 13, 5))
42+
43+
| { str: "l" }
44+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 14, 5))
45+
46+
| { str: "m" }
47+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 15, 5))
48+
49+
| { str: "n" }
50+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 16, 5))
51+
52+
| { str: "o" }
53+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 17, 5))
54+
55+
| { num: 1 }
56+
>num : Symbol(num, Decl(missingDiscriminants2.ts, 18, 5))
57+
58+
const thing1: Thing = { str: "a", num: 0 }
59+
>thing1 : Symbol(thing1, Decl(missingDiscriminants2.ts, 20, 5))
60+
>Thing : Symbol(Thing, Decl(missingDiscriminants2.ts, 0, 0))
61+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 20, 23))
62+
>num : Symbol(num, Decl(missingDiscriminants2.ts, 20, 33))
63+
64+
const thing2: Thing = { str: "b", num: 1 } // Shouldn't be error
65+
>thing2 : Symbol(thing2, Decl(missingDiscriminants2.ts, 21, 5))
66+
>Thing : Symbol(Thing, Decl(missingDiscriminants2.ts, 0, 0))
67+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 21, 23))
68+
>num : Symbol(num, Decl(missingDiscriminants2.ts, 21, 33))
69+
70+
const thing3: Thing = { num: 1, str: "b" } // Shouldn't be error
71+
>thing3 : Symbol(thing3, Decl(missingDiscriminants2.ts, 22, 5))
72+
>Thing : Symbol(Thing, Decl(missingDiscriminants2.ts, 0, 0))
73+
>num : Symbol(num, Decl(missingDiscriminants2.ts, 22, 23))
74+
>str : Symbol(str, Decl(missingDiscriminants2.ts, 22, 31))
75+
76+
type Item =
77+
>Item : Symbol(Item, Decl(missingDiscriminants2.ts, 22, 42))
78+
79+
| { kind: "a", subkind: 0, value: string }
80+
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 25, 5))
81+
>subkind : Symbol(subkind, Decl(missingDiscriminants2.ts, 25, 16))
82+
>value : Symbol(value, Decl(missingDiscriminants2.ts, 25, 28))
83+
84+
| { kind: "a", subkind: 1, value: number }
85+
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 26, 5))
86+
>subkind : Symbol(subkind, Decl(missingDiscriminants2.ts, 26, 16))
87+
>value : Symbol(value, Decl(missingDiscriminants2.ts, 26, 28))
88+
89+
| { kind: "b" }
90+
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 27, 5))
91+
92+
const item1: Item = { subkind: 1, kind: "b" } // Error, type "b" not assignable to type "a"
93+
>item1 : Symbol(item1, Decl(missingDiscriminants2.ts, 29, 5))
94+
>Item : Symbol(Item, Decl(missingDiscriminants2.ts, 22, 42))
95+
>subkind : Symbol(subkind, Decl(missingDiscriminants2.ts, 29, 21))
96+
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 29, 33))
97+
98+
const item2: Item = { kind: "b", subkind: 1 } // Error, 'subkind' isn't a known property
99+
>item2 : Symbol(item2, Decl(missingDiscriminants2.ts, 30, 5))
100+
>Item : Symbol(Item, Decl(missingDiscriminants2.ts, 22, 42))
101+
>kind : Symbol(kind, Decl(missingDiscriminants2.ts, 30, 21))
102+
>subkind : Symbol(subkind, Decl(missingDiscriminants2.ts, 30, 32))
103+
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
//// [tests/cases/compiler/missingDiscriminants2.ts] ////
2+
3+
=== missingDiscriminants2.ts ===
4+
// https://github.com/microsoft/typescript-go/issues/1020
5+
6+
type Thing =
7+
>Thing : Thing
8+
> : ^^^^^
9+
10+
| { str: "a", num: 0 }
11+
>str : "a"
12+
> : ^^^
13+
>num : 0
14+
> : ^
15+
16+
| { str: "b" }
17+
>str : "b"
18+
> : ^^^
19+
20+
| { str: "c" }
21+
>str : "c"
22+
> : ^^^
23+
24+
| { str: "d" }
25+
>str : "d"
26+
> : ^^^
27+
28+
| { str: "e" }
29+
>str : "e"
30+
> : ^^^
31+
32+
| { str: "f" }
33+
>str : "f"
34+
> : ^^^
35+
36+
| { str: "g" }
37+
>str : "g"
38+
> : ^^^
39+
40+
| { str: "h" }
41+
>str : "h"
42+
> : ^^^
43+
44+
| { str: "i" }
45+
>str : "i"
46+
> : ^^^
47+
48+
| { str: "j" }
49+
>str : "j"
50+
> : ^^^
51+
52+
| { str: "k" }
53+
>str : "k"
54+
> : ^^^
55+
56+
| { str: "l" }
57+
>str : "l"
58+
> : ^^^
59+
60+
| { str: "m" }
61+
>str : "m"
62+
> : ^^^
63+
64+
| { str: "n" }
65+
>str : "n"
66+
> : ^^^
67+
68+
| { str: "o" }
69+
>str : "o"
70+
> : ^^^
71+
72+
| { num: 1 }
73+
>num : 1
74+
> : ^
75+
76+
const thing1: Thing = { str: "a", num: 0 }
77+
>thing1 : Thing
78+
> : ^^^^^
79+
>{ str: "a", num: 0 } : { str: "a"; num: 0; }
80+
> : ^^^^^^^^^^^^^^^^^^^^^
81+
>str : "a"
82+
> : ^^^
83+
>"a" : "a"
84+
> : ^^^
85+
>num : 0
86+
> : ^
87+
>0 : 0
88+
> : ^
89+
90+
const thing2: Thing = { str: "b", num: 1 } // Shouldn't be error
91+
>thing2 : Thing
92+
> : ^^^^^
93+
>{ str: "b", num: 1 } : { str: "b"; num: 1; }
94+
> : ^^^^^^^^^^^^^^^^^^^^^
95+
>str : "b"
96+
> : ^^^
97+
>"b" : "b"
98+
> : ^^^
99+
>num : 1
100+
> : ^
101+
>1 : 1
102+
> : ^
103+
104+
const thing3: Thing = { num: 1, str: "b" } // Shouldn't be error
105+
>thing3 : Thing
106+
> : ^^^^^
107+
>{ num: 1, str: "b" } : { num: 1; str: "b"; }
108+
> : ^^^^^^^^^^^^^^^^^^^^^
109+
>num : 1
110+
> : ^
111+
>1 : 1
112+
> : ^
113+
>str : "b"
114+
> : ^^^
115+
>"b" : "b"
116+
> : ^^^
117+
118+
type Item =
119+
>Item : Item
120+
> : ^^^^
121+
122+
| { kind: "a", subkind: 0, value: string }
123+
>kind : "a"
124+
> : ^^^
125+
>subkind : 0
126+
> : ^
127+
>value : string
128+
> : ^^^^^^
129+
130+
| { kind: "a", subkind: 1, value: number }
131+
>kind : "a"
132+
> : ^^^
133+
>subkind : 1
134+
> : ^
135+
>value : number
136+
> : ^^^^^^
137+
138+
| { kind: "b" }
139+
>kind : "b"
140+
> : ^^^
141+
142+
const item1: Item = { subkind: 1, kind: "b" } // Error, type "b" not assignable to type "a"
143+
>item1 : Item
144+
> : ^^^^
145+
>{ subkind: 1, kind: "b" } : { subkind: number; kind: "b"; }
146+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
147+
>subkind : number
148+
> : ^^^^^^
149+
>1 : 1
150+
> : ^
151+
>kind : "b"
152+
> : ^^^
153+
>"b" : "b"
154+
> : ^^^
155+
156+
const item2: Item = { kind: "b", subkind: 1 } // Error, 'subkind' isn't a known property
157+
>item2 : Item
158+
> : ^^^^
159+
>{ kind: "b", subkind: 1 } : { kind: "b"; subkind: number; }
160+
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
161+
>kind : "b"
162+
> : ^^^
163+
>"b" : "b"
164+
> : ^^^
165+
>subkind : number
166+
> : ^^^^^^
167+
>1 : 1
168+
> : ^
169+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// https://github.com/microsoft/typescript-go/issues/1020
5+
6+
type Thing =
7+
| { str: "a", num: 0 }
8+
| { str: "b" }
9+
| { str: "c" }
10+
| { str: "d" }
11+
| { str: "e" }
12+
| { str: "f" }
13+
| { str: "g" }
14+
| { str: "h" }
15+
| { str: "i" }
16+
| { str: "j" }
17+
| { str: "k" }
18+
| { str: "l" }
19+
| { str: "m" }
20+
| { str: "n" }
21+
| { str: "o" }
22+
| { num: 1 }
23+
24+
const thing1: Thing = { str: "a", num: 0 }
25+
const thing2: Thing = { str: "b", num: 1 } // Shouldn't be error
26+
const thing3: Thing = { num: 1, str: "b" } // Shouldn't be error
27+
28+
type Item =
29+
| { kind: "a", subkind: 0, value: string }
30+
| { kind: "a", subkind: 1, value: number }
31+
| { kind: "b" }
32+
33+
const item1: Item = { subkind: 1, kind: "b" } // Error, type "b" not assignable to type "a"
34+
const item2: Item = { kind: "b", subkind: 1 } // Error, 'subkind' isn't a known property

0 commit comments

Comments
 (0)