Skip to content

Commit 98c0460

Browse files
committed
Add tests
1 parent a54709c commit 98c0460

File tree

4 files changed

+426
-0
lines changed

4 files changed

+426
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
tests/cases/compiler/typePredicatesInUnion3.ts(59,24): error TS2345: Argument of type 'number | null' is not assignable to parameter of type 'number'.
2+
Type 'null' is not assignable to type 'number'.
3+
4+
5+
==== tests/cases/compiler/typePredicatesInUnion3.ts (1 errors) ====
6+
// A union of function types is considered a type predicate if at least one constituent is a type
7+
// predicate and the other constituents are matching type predicates or functions returning `false`.
8+
9+
type P1 = (x: unknown) => x is string;
10+
type P2 = (x: unknown) => x is number;
11+
12+
type F1 = (x: unknown) => false;
13+
type F2 = (x: unknown) => boolean;
14+
type F3 = (x: unknown) => string;
15+
16+
function f1(x: unknown, p: P1 | P2) {
17+
if (p(x)) {
18+
x; // string | number
19+
}
20+
}
21+
22+
function f2(x: unknown, p: P1 | P2 | F1) {
23+
if (p(x)) {
24+
x; // string | number
25+
}
26+
}
27+
28+
function f3(x: unknown, p: P1 | P2 | F2) {
29+
if (p(x)) {
30+
x; // unknown
31+
}
32+
}
33+
34+
function f4(x: unknown, p: P1 | P2 | F3) {
35+
if (p(x)) {
36+
x; // unknown
37+
}
38+
}
39+
40+
// Repro from #54143
41+
42+
type HasAttribute<T> = T & { attribute: number };
43+
44+
class Type1 {
45+
attribute: number | null = null;
46+
predicate(): this is HasAttribute<Type1> {
47+
return true;
48+
}
49+
}
50+
51+
class Type2 {
52+
attribute: number | null = null;
53+
predicate(): boolean {
54+
return true;
55+
}
56+
}
57+
58+
function assertType<T>(_val: T) {
59+
}
60+
61+
declare const val: Type1 | Type2;
62+
63+
if (val.predicate()) {
64+
assertType<number>(val.attribute); // Error
65+
~~~~~~~~~~~~~
66+
!!! error TS2345: Argument of type 'number | null' is not assignable to parameter of type 'number'.
67+
!!! error TS2345: Type 'null' is not assignable to type 'number'.
68+
}
69+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
=== tests/cases/compiler/typePredicatesInUnion3.ts ===
2+
// A union of function types is considered a type predicate if at least one constituent is a type
3+
// predicate and the other constituents are matching type predicates or functions returning `false`.
4+
5+
type P1 = (x: unknown) => x is string;
6+
>P1 : Symbol(P1, Decl(typePredicatesInUnion3.ts, 0, 0))
7+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 3, 11))
8+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 3, 11))
9+
10+
type P2 = (x: unknown) => x is number;
11+
>P2 : Symbol(P2, Decl(typePredicatesInUnion3.ts, 3, 38))
12+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 4, 11))
13+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 4, 11))
14+
15+
type F1 = (x: unknown) => false;
16+
>F1 : Symbol(F1, Decl(typePredicatesInUnion3.ts, 4, 38))
17+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 6, 11))
18+
19+
type F2 = (x: unknown) => boolean;
20+
>F2 : Symbol(F2, Decl(typePredicatesInUnion3.ts, 6, 32))
21+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 7, 11))
22+
23+
type F3 = (x: unknown) => string;
24+
>F3 : Symbol(F3, Decl(typePredicatesInUnion3.ts, 7, 34))
25+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 8, 11))
26+
27+
function f1(x: unknown, p: P1 | P2) {
28+
>f1 : Symbol(f1, Decl(typePredicatesInUnion3.ts, 8, 33))
29+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 10, 12))
30+
>p : Symbol(p, Decl(typePredicatesInUnion3.ts, 10, 23))
31+
>P1 : Symbol(P1, Decl(typePredicatesInUnion3.ts, 0, 0))
32+
>P2 : Symbol(P2, Decl(typePredicatesInUnion3.ts, 3, 38))
33+
34+
if (p(x)) {
35+
>p : Symbol(p, Decl(typePredicatesInUnion3.ts, 10, 23))
36+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 10, 12))
37+
38+
x; // string | number
39+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 10, 12))
40+
}
41+
}
42+
43+
function f2(x: unknown, p: P1 | P2 | F1) {
44+
>f2 : Symbol(f2, Decl(typePredicatesInUnion3.ts, 14, 1))
45+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 16, 12))
46+
>p : Symbol(p, Decl(typePredicatesInUnion3.ts, 16, 23))
47+
>P1 : Symbol(P1, Decl(typePredicatesInUnion3.ts, 0, 0))
48+
>P2 : Symbol(P2, Decl(typePredicatesInUnion3.ts, 3, 38))
49+
>F1 : Symbol(F1, Decl(typePredicatesInUnion3.ts, 4, 38))
50+
51+
if (p(x)) {
52+
>p : Symbol(p, Decl(typePredicatesInUnion3.ts, 16, 23))
53+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 16, 12))
54+
55+
x; // string | number
56+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 16, 12))
57+
}
58+
}
59+
60+
function f3(x: unknown, p: P1 | P2 | F2) {
61+
>f3 : Symbol(f3, Decl(typePredicatesInUnion3.ts, 20, 1))
62+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 22, 12))
63+
>p : Symbol(p, Decl(typePredicatesInUnion3.ts, 22, 23))
64+
>P1 : Symbol(P1, Decl(typePredicatesInUnion3.ts, 0, 0))
65+
>P2 : Symbol(P2, Decl(typePredicatesInUnion3.ts, 3, 38))
66+
>F2 : Symbol(F2, Decl(typePredicatesInUnion3.ts, 6, 32))
67+
68+
if (p(x)) {
69+
>p : Symbol(p, Decl(typePredicatesInUnion3.ts, 22, 23))
70+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 22, 12))
71+
72+
x; // unknown
73+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 22, 12))
74+
}
75+
}
76+
77+
function f4(x: unknown, p: P1 | P2 | F3) {
78+
>f4 : Symbol(f4, Decl(typePredicatesInUnion3.ts, 26, 1))
79+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 28, 12))
80+
>p : Symbol(p, Decl(typePredicatesInUnion3.ts, 28, 23))
81+
>P1 : Symbol(P1, Decl(typePredicatesInUnion3.ts, 0, 0))
82+
>P2 : Symbol(P2, Decl(typePredicatesInUnion3.ts, 3, 38))
83+
>F3 : Symbol(F3, Decl(typePredicatesInUnion3.ts, 7, 34))
84+
85+
if (p(x)) {
86+
>p : Symbol(p, Decl(typePredicatesInUnion3.ts, 28, 23))
87+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 28, 12))
88+
89+
x; // unknown
90+
>x : Symbol(x, Decl(typePredicatesInUnion3.ts, 28, 12))
91+
}
92+
}
93+
94+
// Repro from #54143
95+
96+
type HasAttribute<T> = T & { attribute: number };
97+
>HasAttribute : Symbol(HasAttribute, Decl(typePredicatesInUnion3.ts, 32, 1))
98+
>T : Symbol(T, Decl(typePredicatesInUnion3.ts, 36, 18))
99+
>T : Symbol(T, Decl(typePredicatesInUnion3.ts, 36, 18))
100+
>attribute : Symbol(attribute, Decl(typePredicatesInUnion3.ts, 36, 28))
101+
102+
class Type1 {
103+
>Type1 : Symbol(Type1, Decl(typePredicatesInUnion3.ts, 36, 49))
104+
105+
attribute: number | null = null;
106+
>attribute : Symbol(Type1.attribute, Decl(typePredicatesInUnion3.ts, 38, 13))
107+
108+
predicate(): this is HasAttribute<Type1> {
109+
>predicate : Symbol(Type1.predicate, Decl(typePredicatesInUnion3.ts, 39, 36))
110+
>HasAttribute : Symbol(HasAttribute, Decl(typePredicatesInUnion3.ts, 32, 1))
111+
>Type1 : Symbol(Type1, Decl(typePredicatesInUnion3.ts, 36, 49))
112+
113+
return true;
114+
}
115+
}
116+
117+
class Type2 {
118+
>Type2 : Symbol(Type2, Decl(typePredicatesInUnion3.ts, 43, 1))
119+
120+
attribute: number | null = null;
121+
>attribute : Symbol(Type2.attribute, Decl(typePredicatesInUnion3.ts, 45, 13))
122+
123+
predicate(): boolean {
124+
>predicate : Symbol(Type2.predicate, Decl(typePredicatesInUnion3.ts, 46, 36))
125+
126+
return true;
127+
}
128+
}
129+
130+
function assertType<T>(_val: T) {
131+
>assertType : Symbol(assertType, Decl(typePredicatesInUnion3.ts, 50, 1))
132+
>T : Symbol(T, Decl(typePredicatesInUnion3.ts, 52, 20))
133+
>_val : Symbol(_val, Decl(typePredicatesInUnion3.ts, 52, 23))
134+
>T : Symbol(T, Decl(typePredicatesInUnion3.ts, 52, 20))
135+
}
136+
137+
declare const val: Type1 | Type2;
138+
>val : Symbol(val, Decl(typePredicatesInUnion3.ts, 55, 13))
139+
>Type1 : Symbol(Type1, Decl(typePredicatesInUnion3.ts, 36, 49))
140+
>Type2 : Symbol(Type2, Decl(typePredicatesInUnion3.ts, 43, 1))
141+
142+
if (val.predicate()) {
143+
>val.predicate : Symbol(predicate, Decl(typePredicatesInUnion3.ts, 39, 36), Decl(typePredicatesInUnion3.ts, 46, 36))
144+
>val : Symbol(val, Decl(typePredicatesInUnion3.ts, 55, 13))
145+
>predicate : Symbol(predicate, Decl(typePredicatesInUnion3.ts, 39, 36), Decl(typePredicatesInUnion3.ts, 46, 36))
146+
147+
assertType<number>(val.attribute); // Error
148+
>assertType : Symbol(assertType, Decl(typePredicatesInUnion3.ts, 50, 1))
149+
>val.attribute : Symbol(attribute, Decl(typePredicatesInUnion3.ts, 38, 13), Decl(typePredicatesInUnion3.ts, 45, 13))
150+
>val : Symbol(val, Decl(typePredicatesInUnion3.ts, 55, 13))
151+
>attribute : Symbol(attribute, Decl(typePredicatesInUnion3.ts, 38, 13), Decl(typePredicatesInUnion3.ts, 45, 13))
152+
}
153+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
=== tests/cases/compiler/typePredicatesInUnion3.ts ===
2+
// A union of function types is considered a type predicate if at least one constituent is a type
3+
// predicate and the other constituents are matching type predicates or functions returning `false`.
4+
5+
type P1 = (x: unknown) => x is string;
6+
>P1 : (x: unknown) => x is string
7+
>x : unknown
8+
9+
type P2 = (x: unknown) => x is number;
10+
>P2 : (x: unknown) => x is number
11+
>x : unknown
12+
13+
type F1 = (x: unknown) => false;
14+
>F1 : (x: unknown) => false
15+
>x : unknown
16+
>false : false
17+
18+
type F2 = (x: unknown) => boolean;
19+
>F2 : (x: unknown) => boolean
20+
>x : unknown
21+
22+
type F3 = (x: unknown) => string;
23+
>F3 : (x: unknown) => string
24+
>x : unknown
25+
26+
function f1(x: unknown, p: P1 | P2) {
27+
>f1 : (x: unknown, p: P1 | P2) => void
28+
>x : unknown
29+
>p : P1 | P2
30+
31+
if (p(x)) {
32+
>p(x) : boolean
33+
>p : P1 | P2
34+
>x : unknown
35+
36+
x; // string | number
37+
>x : string | number
38+
}
39+
}
40+
41+
function f2(x: unknown, p: P1 | P2 | F1) {
42+
>f2 : (x: unknown, p: P1 | P2 | F1) => void
43+
>x : unknown
44+
>p : P1 | P2 | F1
45+
46+
if (p(x)) {
47+
>p(x) : boolean
48+
>p : P1 | P2 | F1
49+
>x : unknown
50+
51+
x; // string | number
52+
>x : string | number
53+
}
54+
}
55+
56+
function f3(x: unknown, p: P1 | P2 | F2) {
57+
>f3 : (x: unknown, p: P1 | P2 | F2) => void
58+
>x : unknown
59+
>p : P1 | P2 | F2
60+
61+
if (p(x)) {
62+
>p(x) : boolean
63+
>p : P1 | P2 | F2
64+
>x : unknown
65+
66+
x; // unknown
67+
>x : unknown
68+
}
69+
}
70+
71+
function f4(x: unknown, p: P1 | P2 | F3) {
72+
>f4 : (x: unknown, p: P1 | P2 | F3) => void
73+
>x : unknown
74+
>p : P1 | P2 | F3
75+
76+
if (p(x)) {
77+
>p(x) : string | boolean
78+
>p : P1 | P2 | F3
79+
>x : unknown
80+
81+
x; // unknown
82+
>x : unknown
83+
}
84+
}
85+
86+
// Repro from #54143
87+
88+
type HasAttribute<T> = T & { attribute: number };
89+
>HasAttribute : HasAttribute<T>
90+
>attribute : number
91+
92+
class Type1 {
93+
>Type1 : Type1
94+
95+
attribute: number | null = null;
96+
>attribute : number | null
97+
98+
predicate(): this is HasAttribute<Type1> {
99+
>predicate : () => this is HasAttribute<Type1>
100+
101+
return true;
102+
>true : true
103+
}
104+
}
105+
106+
class Type2 {
107+
>Type2 : Type2
108+
109+
attribute: number | null = null;
110+
>attribute : number | null
111+
112+
predicate(): boolean {
113+
>predicate : () => boolean
114+
115+
return true;
116+
>true : true
117+
}
118+
}
119+
120+
function assertType<T>(_val: T) {
121+
>assertType : <T>(_val: T) => void
122+
>_val : T
123+
}
124+
125+
declare const val: Type1 | Type2;
126+
>val : Type1 | Type2
127+
128+
if (val.predicate()) {
129+
>val.predicate() : boolean
130+
>val.predicate : (() => this is HasAttribute<Type1>) | (() => boolean)
131+
>val : Type1 | Type2
132+
>predicate : (() => this is HasAttribute<Type1>) | (() => boolean)
133+
134+
assertType<number>(val.attribute); // Error
135+
>assertType<number>(val.attribute) : void
136+
>assertType : <T>(_val: T) => void
137+
>val.attribute : number | null
138+
>val : Type1 | Type2
139+
>attribute : number | null
140+
}
141+

0 commit comments

Comments
 (0)