Skip to content

Commit 3f0423d

Browse files
committed
fix(46909):Fix typePredicate in UnionType
1 parent 0019c01 commit 3f0423d

File tree

5 files changed

+293
-1
lines changed

5 files changed

+293
-1
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24735,7 +24735,15 @@ namespace ts {
2473524735
// If the current type is a union type, remove all constituents that couldn't be instances of
2473624736
// the candidate type. If one or more constituents remain, return a union of those.
2473724737
if (type.flags & TypeFlags.Union) {
24738-
const assignableType = filterType(type, t => isRelated(t, candidate));
24738+
let assignableType = filterType(type, t => isRelated(t, candidate));
24739+
if(candidate.flags & TypeFlags.Union){
24740+
const unionAssignableType = mapType(type, type => {
24741+
return filterType(candidate, candidate => isRelated(candidate, type));
24742+
});
24743+
if (!isTypeSubsetOf(unionAssignableType, assignableType)) {
24744+
assignableType = unionAssignableType;
24745+
}
24746+
}
2473924747
if (!(assignableType.flags & TypeFlags.Never)) {
2474024748
return assignableType;
2474124749
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//// [typePredicatesInUnion3.ts]
2+
function test1(x: string | 0) {
3+
if (check1(x)) {
4+
x
5+
}
6+
if (check2(x)) {
7+
x
8+
}
9+
}
10+
11+
function test2(x: string | number) {
12+
if (check1(x)) {
13+
x
14+
}
15+
if (check2(x)) {
16+
x
17+
}
18+
}
19+
20+
21+
function test3(x: "hello" | number) {
22+
if (check1(x)) {
23+
x
24+
}
25+
if (check2(x)) {
26+
x
27+
}
28+
}
29+
30+
function check1(x: string | number): x is ("hello" | 0) {
31+
return x === "hello" || x === 0;
32+
}
33+
34+
function check2(x: string | number): x is ("hello" | "bye" | 0) {
35+
return x === "hello" || x === "bye" || x === 0;
36+
}
37+
38+
//// [typePredicatesInUnion3.js]
39+
function test1(x) {
40+
if (check1(x)) {
41+
x;
42+
}
43+
if (check2(x)) {
44+
x;
45+
}
46+
}
47+
function test2(x) {
48+
if (check1(x)) {
49+
x;
50+
}
51+
if (check2(x)) {
52+
x;
53+
}
54+
}
55+
function test3(x) {
56+
if (check1(x)) {
57+
x;
58+
}
59+
if (check2(x)) {
60+
x;
61+
}
62+
}
63+
function check1(x) {
64+
return x === "hello" || x === 0;
65+
}
66+
function check2(x) {
67+
return x === "hello" || x === "bye" || x === 0;
68+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
=== tests/cases/compiler/typePredicatesInUnion3.ts ===
2+
function test1(x: string | 0) {
3+
>test1 : Symbol(test1, Decl(typePredicatesInUnion3.ts, 0, 0))
4+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 0, 15))
5+
6+
if (check1(x)) {
7+
>check1 : Symbol(check1, Decl(typePredicatesInUnion3.ts, 26, 1))
8+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 0, 15))
9+
10+
x
11+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 0, 15))
12+
}
13+
if (check2(x)) {
14+
>check2 : Symbol(check2, Decl(typePredicatesInUnion3.ts, 30, 1))
15+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 0, 15))
16+
17+
x
18+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 0, 15))
19+
}
20+
}
21+
22+
function test2(x: string | number) {
23+
>test2 : Symbol(test2, Decl(typePredicatesInUnion3.ts, 7, 1))
24+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 9, 15))
25+
26+
if (check1(x)) {
27+
>check1 : Symbol(check1, Decl(typePredicatesInUnion3.ts, 26, 1))
28+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 9, 15))
29+
30+
x
31+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 9, 15))
32+
}
33+
if (check2(x)) {
34+
>check2 : Symbol(check2, Decl(typePredicatesInUnion3.ts, 30, 1))
35+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 9, 15))
36+
37+
x
38+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 9, 15))
39+
}
40+
}
41+
42+
43+
function test3(x: "hello" | number) {
44+
>test3 : Symbol(test3, Decl(typePredicatesInUnion3.ts, 16, 1))
45+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 19, 15))
46+
47+
if (check1(x)) {
48+
>check1 : Symbol(check1, Decl(typePredicatesInUnion3.ts, 26, 1))
49+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 19, 15))
50+
51+
x
52+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 19, 15))
53+
}
54+
if (check2(x)) {
55+
>check2 : Symbol(check2, Decl(typePredicatesInUnion3.ts, 30, 1))
56+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 19, 15))
57+
58+
x
59+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 19, 15))
60+
}
61+
}
62+
63+
function check1(x: string | number): x is ("hello" | 0) {
64+
>check1 : Symbol(check1, Decl(typePredicatesInUnion3.ts, 26, 1))
65+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 28, 16))
66+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 28, 16))
67+
68+
return x === "hello" || x === 0;
69+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 28, 16))
70+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 28, 16))
71+
}
72+
73+
function check2(x: string | number): x is ("hello" | "bye" | 0) {
74+
>check2 : Symbol(check2, Decl(typePredicatesInUnion3.ts, 30, 1))
75+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 32, 16))
76+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 32, 16))
77+
78+
return x === "hello" || x === "bye" || x === 0;
79+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 32, 16))
80+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 32, 16))
81+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 32, 16))
82+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
=== tests/cases/compiler/typePredicatesInUnion3.ts ===
2+
function test1(x: string | 0) {
3+
>test1 : (x: string | 0) => void
4+
>x : string | 0
5+
6+
if (check1(x)) {
7+
>check1(x) : boolean
8+
>check1 : (x: string | number) => x is 0 | "hello"
9+
>x : string | 0
10+
11+
x
12+
>x : 0 | "hello"
13+
}
14+
if (check2(x)) {
15+
>check2(x) : boolean
16+
>check2 : (x: string | number) => x is 0 | "hello" | "bye"
17+
>x : string | 0
18+
19+
x
20+
>x : 0 | "hello" | "bye"
21+
}
22+
}
23+
24+
function test2(x: string | number) {
25+
>test2 : (x: string | number) => void
26+
>x : string | number
27+
28+
if (check1(x)) {
29+
>check1(x) : boolean
30+
>check1 : (x: string | number) => x is 0 | "hello"
31+
>x : string | number
32+
33+
x
34+
>x : 0 | "hello"
35+
}
36+
if (check2(x)) {
37+
>check2(x) : boolean
38+
>check2 : (x: string | number) => x is 0 | "hello" | "bye"
39+
>x : string | number
40+
41+
x
42+
>x : 0 | "hello" | "bye"
43+
}
44+
}
45+
46+
47+
function test3(x: "hello" | number) {
48+
>test3 : (x: "hello" | number) => void
49+
>x : number | "hello"
50+
51+
if (check1(x)) {
52+
>check1(x) : boolean
53+
>check1 : (x: string | number) => x is 0 | "hello"
54+
>x : number | "hello"
55+
56+
x
57+
>x : 0 | "hello"
58+
}
59+
if (check2(x)) {
60+
>check2(x) : boolean
61+
>check2 : (x: string | number) => x is 0 | "hello" | "bye"
62+
>x : number | "hello"
63+
64+
x
65+
>x : 0 | "hello"
66+
}
67+
}
68+
69+
function check1(x: string | number): x is ("hello" | 0) {
70+
>check1 : (x: string | number) => x is 0 | "hello"
71+
>x : string | number
72+
73+
return x === "hello" || x === 0;
74+
>x === "hello" || x === 0 : boolean
75+
>x === "hello" : boolean
76+
>x : string | number
77+
>"hello" : "hello"
78+
>x === 0 : boolean
79+
>x : string | number
80+
>0 : 0
81+
}
82+
83+
function check2(x: string | number): x is ("hello" | "bye" | 0) {
84+
>check2 : (x: string | number) => x is 0 | "hello" | "bye"
85+
>x : string | number
86+
87+
return x === "hello" || x === "bye" || x === 0;
88+
>x === "hello" || x === "bye" || x === 0 : boolean
89+
>x === "hello" || x === "bye" : boolean
90+
>x === "hello" : boolean
91+
>x : string | number
92+
>"hello" : "hello"
93+
>x === "bye" : boolean
94+
>x : string | number
95+
>"bye" : "bye"
96+
>x === 0 : boolean
97+
>x : string | number
98+
>0 : 0
99+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
function test1(x: string | 0) {
2+
if (check1(x)) {
3+
x
4+
}
5+
if (check2(x)) {
6+
x
7+
}
8+
}
9+
10+
function test2(x: string | number) {
11+
if (check1(x)) {
12+
x
13+
}
14+
if (check2(x)) {
15+
x
16+
}
17+
}
18+
19+
20+
function test3(x: "hello" | number) {
21+
if (check1(x)) {
22+
x
23+
}
24+
if (check2(x)) {
25+
x
26+
}
27+
}
28+
29+
function check1(x: string | number): x is ("hello" | 0) {
30+
return x === "hello" || x === 0;
31+
}
32+
33+
function check2(x: string | number): x is ("hello" | "bye" | 0) {
34+
return x === "hello" || x === "bye" || x === 0;
35+
}

0 commit comments

Comments
 (0)