Skip to content

Commit 6a011b5

Browse files
Andaristsnovader
authored andcommitted
Discriminate types with divergent read/write property types (microsoft#55576)
1 parent 4976f4a commit 6a011b5

File tree

25 files changed

+2086
-1
lines changed

25 files changed

+2086
-1
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14389,7 +14389,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1438914389
if (writeTypes || writeType !== type) {
1439014390
writeTypes = append(!writeTypes ? propTypes.slice() : writeTypes, writeType);
1439114391
}
14392-
else if (type !== firstType) {
14392+
if (type !== firstType) {
1439314393
checkFlags |= CheckFlags.HasNonUniformType;
1439414394
}
1439514395
if (isLiteralType(type) || isPatternLiteralType(type)) {
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//// [tests/cases/compiler/discriminateWithDivergentAccessors1.ts] ////
2+
3+
=== discriminateWithDivergentAccessors1.ts ===
4+
type WeirdoBox<T> =
5+
>WeirdoBox : Symbol(WeirdoBox, Decl(discriminateWithDivergentAccessors1.ts, 0, 0))
6+
>T : Symbol(T, Decl(discriminateWithDivergentAccessors1.ts, 0, 15))
7+
8+
| { get done(): false; set done(v: T | null) }
9+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 1, 5), Decl(discriminateWithDivergentAccessors1.ts, 1, 24))
10+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 1, 5), Decl(discriminateWithDivergentAccessors1.ts, 1, 24))
11+
>v : Symbol(v, Decl(discriminateWithDivergentAccessors1.ts, 1, 34))
12+
>T : Symbol(T, Decl(discriminateWithDivergentAccessors1.ts, 0, 15))
13+
14+
| { get done(): true; set done(v: T | null); value: T };
15+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 2, 5), Decl(discriminateWithDivergentAccessors1.ts, 2, 23))
16+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 2, 5), Decl(discriminateWithDivergentAccessors1.ts, 2, 23))
17+
>v : Symbol(v, Decl(discriminateWithDivergentAccessors1.ts, 2, 33))
18+
>T : Symbol(T, Decl(discriminateWithDivergentAccessors1.ts, 0, 15))
19+
>value : Symbol(value, Decl(discriminateWithDivergentAccessors1.ts, 2, 46))
20+
>T : Symbol(T, Decl(discriminateWithDivergentAccessors1.ts, 0, 15))
21+
22+
declare const weirdoBox: WeirdoBox<number>;
23+
>weirdoBox : Symbol(weirdoBox, Decl(discriminateWithDivergentAccessors1.ts, 4, 13))
24+
>WeirdoBox : Symbol(WeirdoBox, Decl(discriminateWithDivergentAccessors1.ts, 0, 0))
25+
26+
if (weirdoBox.done) {
27+
>weirdoBox.done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 1, 5), Decl(discriminateWithDivergentAccessors1.ts, 1, 24), Decl(discriminateWithDivergentAccessors1.ts, 2, 5), Decl(discriminateWithDivergentAccessors1.ts, 2, 23))
28+
>weirdoBox : Symbol(weirdoBox, Decl(discriminateWithDivergentAccessors1.ts, 4, 13))
29+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 1, 5), Decl(discriminateWithDivergentAccessors1.ts, 1, 24), Decl(discriminateWithDivergentAccessors1.ts, 2, 5), Decl(discriminateWithDivergentAccessors1.ts, 2, 23))
30+
31+
weirdoBox.value;
32+
>weirdoBox.value : Symbol(value, Decl(discriminateWithDivergentAccessors1.ts, 2, 46))
33+
>weirdoBox : Symbol(weirdoBox, Decl(discriminateWithDivergentAccessors1.ts, 4, 13))
34+
>value : Symbol(value, Decl(discriminateWithDivergentAccessors1.ts, 2, 46))
35+
}
36+
37+
type WeirdoBox2<T> =
38+
>WeirdoBox2 : Symbol(WeirdoBox2, Decl(discriminateWithDivergentAccessors1.ts, 8, 1))
39+
>T : Symbol(T, Decl(discriminateWithDivergentAccessors1.ts, 10, 16))
40+
41+
| { get done(): false; set done(v: T | null) }
42+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 11, 5), Decl(discriminateWithDivergentAccessors1.ts, 11, 24))
43+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 11, 5), Decl(discriminateWithDivergentAccessors1.ts, 11, 24))
44+
>v : Symbol(v, Decl(discriminateWithDivergentAccessors1.ts, 11, 34))
45+
>T : Symbol(T, Decl(discriminateWithDivergentAccessors1.ts, 10, 16))
46+
47+
| { get done(): true; set done(v: T | null); value: T }
48+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 12, 5), Decl(discriminateWithDivergentAccessors1.ts, 12, 23))
49+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 12, 5), Decl(discriminateWithDivergentAccessors1.ts, 12, 23))
50+
>v : Symbol(v, Decl(discriminateWithDivergentAccessors1.ts, 12, 33))
51+
>T : Symbol(T, Decl(discriminateWithDivergentAccessors1.ts, 10, 16))
52+
>value : Symbol(value, Decl(discriminateWithDivergentAccessors1.ts, 12, 46))
53+
>T : Symbol(T, Decl(discriminateWithDivergentAccessors1.ts, 10, 16))
54+
55+
| { get done(): true; set done(v: T | null | undefined); value: number };
56+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 13, 5), Decl(discriminateWithDivergentAccessors1.ts, 13, 23))
57+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 13, 5), Decl(discriminateWithDivergentAccessors1.ts, 13, 23))
58+
>v : Symbol(v, Decl(discriminateWithDivergentAccessors1.ts, 13, 33))
59+
>T : Symbol(T, Decl(discriminateWithDivergentAccessors1.ts, 10, 16))
60+
>value : Symbol(value, Decl(discriminateWithDivergentAccessors1.ts, 13, 58))
61+
62+
declare const weirdoBox2: WeirdoBox2<string>;
63+
>weirdoBox2 : Symbol(weirdoBox2, Decl(discriminateWithDivergentAccessors1.ts, 15, 13))
64+
>WeirdoBox2 : Symbol(WeirdoBox2, Decl(discriminateWithDivergentAccessors1.ts, 8, 1))
65+
66+
if (weirdoBox2.done) {
67+
>weirdoBox2.done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 11, 5), Decl(discriminateWithDivergentAccessors1.ts, 11, 24), Decl(discriminateWithDivergentAccessors1.ts, 12, 5), Decl(discriminateWithDivergentAccessors1.ts, 12, 23), Decl(discriminateWithDivergentAccessors1.ts, 13, 5) ... and 1 more)
68+
>weirdoBox2 : Symbol(weirdoBox2, Decl(discriminateWithDivergentAccessors1.ts, 15, 13))
69+
>done : Symbol(done, Decl(discriminateWithDivergentAccessors1.ts, 11, 5), Decl(discriminateWithDivergentAccessors1.ts, 11, 24), Decl(discriminateWithDivergentAccessors1.ts, 12, 5), Decl(discriminateWithDivergentAccessors1.ts, 12, 23), Decl(discriminateWithDivergentAccessors1.ts, 13, 5) ... and 1 more)
70+
71+
weirdoBox2.value;
72+
>weirdoBox2.value : Symbol(value, Decl(discriminateWithDivergentAccessors1.ts, 12, 46), Decl(discriminateWithDivergentAccessors1.ts, 13, 58))
73+
>weirdoBox2 : Symbol(weirdoBox2, Decl(discriminateWithDivergentAccessors1.ts, 15, 13))
74+
>value : Symbol(value, Decl(discriminateWithDivergentAccessors1.ts, 12, 46), Decl(discriminateWithDivergentAccessors1.ts, 13, 58))
75+
}
76+
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//// [tests/cases/compiler/discriminateWithDivergentAccessors1.ts] ////
2+
3+
=== discriminateWithDivergentAccessors1.ts ===
4+
type WeirdoBox<T> =
5+
>WeirdoBox : WeirdoBox<T>
6+
7+
| { get done(): false; set done(v: T | null) }
8+
>done : false
9+
>false : false
10+
>done : false
11+
>v : T | null
12+
13+
| { get done(): true; set done(v: T | null); value: T };
14+
>done : true
15+
>true : true
16+
>done : true
17+
>v : T | null
18+
>value : T
19+
20+
declare const weirdoBox: WeirdoBox<number>;
21+
>weirdoBox : WeirdoBox<number>
22+
23+
if (weirdoBox.done) {
24+
>weirdoBox.done : boolean
25+
>weirdoBox : WeirdoBox<number>
26+
>done : boolean
27+
28+
weirdoBox.value;
29+
>weirdoBox.value : number
30+
>weirdoBox : { done: true; value: number; }
31+
>value : number
32+
}
33+
34+
type WeirdoBox2<T> =
35+
>WeirdoBox2 : WeirdoBox2<T>
36+
37+
| { get done(): false; set done(v: T | null) }
38+
>done : false
39+
>false : false
40+
>done : false
41+
>v : T | null
42+
43+
| { get done(): true; set done(v: T | null); value: T }
44+
>done : true
45+
>true : true
46+
>done : true
47+
>v : T | null
48+
>value : T
49+
50+
| { get done(): true; set done(v: T | null | undefined); value: number };
51+
>done : true
52+
>true : true
53+
>done : true
54+
>v : T | null | undefined
55+
>value : number
56+
57+
declare const weirdoBox2: WeirdoBox2<string>;
58+
>weirdoBox2 : WeirdoBox2<string>
59+
60+
if (weirdoBox2.done) {
61+
>weirdoBox2.done : boolean
62+
>weirdoBox2 : WeirdoBox2<string>
63+
>done : boolean
64+
65+
weirdoBox2.value;
66+
>weirdoBox2.value : string | number
67+
>weirdoBox2 : { done: true; value: string; } | { done: true; value: number; }
68+
>value : string | number
69+
}
70+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [tests/cases/compiler/discriminateWithOptionalProperty1.ts] ////
2+
3+
=== discriminateWithOptionalProperty1.ts ===
4+
type Box<T> = { done?: false } | { done: true; value: T };
5+
>Box : Symbol(Box, Decl(discriminateWithOptionalProperty1.ts, 0, 0))
6+
>T : Symbol(T, Decl(discriminateWithOptionalProperty1.ts, 0, 9))
7+
>done : Symbol(done, Decl(discriminateWithOptionalProperty1.ts, 0, 15))
8+
>done : Symbol(done, Decl(discriminateWithOptionalProperty1.ts, 0, 34))
9+
>value : Symbol(value, Decl(discriminateWithOptionalProperty1.ts, 0, 46))
10+
>T : Symbol(T, Decl(discriminateWithOptionalProperty1.ts, 0, 9))
11+
12+
declare const box: Box<number>;
13+
>box : Symbol(box, Decl(discriminateWithOptionalProperty1.ts, 2, 13))
14+
>Box : Symbol(Box, Decl(discriminateWithOptionalProperty1.ts, 0, 0))
15+
16+
if (box.done) {
17+
>box.done : Symbol(done, Decl(discriminateWithOptionalProperty1.ts, 0, 15), Decl(discriminateWithOptionalProperty1.ts, 0, 34))
18+
>box : Symbol(box, Decl(discriminateWithOptionalProperty1.ts, 2, 13))
19+
>done : Symbol(done, Decl(discriminateWithOptionalProperty1.ts, 0, 15), Decl(discriminateWithOptionalProperty1.ts, 0, 34))
20+
21+
box.value;
22+
>box.value : Symbol(value, Decl(discriminateWithOptionalProperty1.ts, 0, 46))
23+
>box : Symbol(box, Decl(discriminateWithOptionalProperty1.ts, 2, 13))
24+
>value : Symbol(value, Decl(discriminateWithOptionalProperty1.ts, 0, 46))
25+
}
26+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [tests/cases/compiler/discriminateWithOptionalProperty1.ts] ////
2+
3+
=== discriminateWithOptionalProperty1.ts ===
4+
type Box<T> = { done?: false } | { done: true; value: T };
5+
>Box : Box<T>
6+
>done : false | undefined
7+
>false : false
8+
>done : true
9+
>true : true
10+
>value : T
11+
12+
declare const box: Box<number>;
13+
>box : Box<number>
14+
15+
if (box.done) {
16+
>box.done : boolean | undefined
17+
>box : Box<number>
18+
>done : boolean | undefined
19+
20+
box.value;
21+
>box.value : number
22+
>box : { done: true; value: number; }
23+
>value : number
24+
}
25+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [tests/cases/compiler/discriminateWithOptionalProperty1.ts] ////
2+
3+
=== discriminateWithOptionalProperty1.ts ===
4+
type Box<T> = { done?: false } | { done: true; value: T };
5+
>Box : Symbol(Box, Decl(discriminateWithOptionalProperty1.ts, 0, 0))
6+
>T : Symbol(T, Decl(discriminateWithOptionalProperty1.ts, 0, 9))
7+
>done : Symbol(done, Decl(discriminateWithOptionalProperty1.ts, 0, 15))
8+
>done : Symbol(done, Decl(discriminateWithOptionalProperty1.ts, 0, 34))
9+
>value : Symbol(value, Decl(discriminateWithOptionalProperty1.ts, 0, 46))
10+
>T : Symbol(T, Decl(discriminateWithOptionalProperty1.ts, 0, 9))
11+
12+
declare const box: Box<number>;
13+
>box : Symbol(box, Decl(discriminateWithOptionalProperty1.ts, 2, 13))
14+
>Box : Symbol(Box, Decl(discriminateWithOptionalProperty1.ts, 0, 0))
15+
16+
if (box.done) {
17+
>box.done : Symbol(done, Decl(discriminateWithOptionalProperty1.ts, 0, 15), Decl(discriminateWithOptionalProperty1.ts, 0, 34))
18+
>box : Symbol(box, Decl(discriminateWithOptionalProperty1.ts, 2, 13))
19+
>done : Symbol(done, Decl(discriminateWithOptionalProperty1.ts, 0, 15), Decl(discriminateWithOptionalProperty1.ts, 0, 34))
20+
21+
box.value;
22+
>box.value : Symbol(value, Decl(discriminateWithOptionalProperty1.ts, 0, 46))
23+
>box : Symbol(box, Decl(discriminateWithOptionalProperty1.ts, 2, 13))
24+
>value : Symbol(value, Decl(discriminateWithOptionalProperty1.ts, 0, 46))
25+
}
26+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [tests/cases/compiler/discriminateWithOptionalProperty1.ts] ////
2+
3+
=== discriminateWithOptionalProperty1.ts ===
4+
type Box<T> = { done?: false } | { done: true; value: T };
5+
>Box : Box<T>
6+
>done : false | undefined
7+
>false : false
8+
>done : true
9+
>true : true
10+
>value : T
11+
12+
declare const box: Box<number>;
13+
>box : Box<number>
14+
15+
if (box.done) {
16+
>box.done : boolean | undefined
17+
>box : Box<number>
18+
>done : boolean | undefined
19+
20+
box.value;
21+
>box.value : number
22+
>box : { done: true; value: number; }
23+
>value : number
24+
}
25+

0 commit comments

Comments
 (0)