Skip to content

Commit a0fbf5c

Browse files
committed
Add tests
1 parent 13cf64e commit a0fbf5c

File tree

5 files changed

+926
-0
lines changed

5 files changed

+926
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(49,11): error TS2339: Property 'foo' does not exist on type 'MyUnion'.
2+
Property 'foo' does not exist on type 'AA'.
3+
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(58,44): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
4+
tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(59,11): error TS2339: Property 'foo' does not exist on type 'MyUnion'.
5+
Property 'foo' does not exist on type 'AA'.
6+
7+
8+
==== tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts (3 errors) ====
9+
function f1<T extends string | undefined>(x: T, y: { a: T }, z: [T]): string {
10+
if (x) {
11+
x;
12+
x.length;
13+
return x;
14+
}
15+
if (y.a) {
16+
y.a.length;
17+
return y.a;
18+
}
19+
if (z[0]) {
20+
z[0].length;
21+
return z[0];
22+
}
23+
return "hello";
24+
}
25+
26+
function f2<T>(x: Extract<T, string | undefined> | null): string {
27+
if (x) {
28+
x;
29+
x.length;
30+
return x;
31+
}
32+
return "hello";
33+
}
34+
35+
// Repro from #13995
36+
37+
declare function takeA(val: 'A'): void;
38+
export function bounceAndTakeIfA<AB extends 'A' | 'B'>(value: AB): AB {
39+
if (value === 'A') {
40+
takeA(value);
41+
return value;
42+
}
43+
else {
44+
return value;
45+
}
46+
}
47+
48+
// Repro from #13995
49+
50+
type Common = { id: number };
51+
type AA = { tag: 'A', id: number };
52+
type BB = { tag: 'B', id: number, foo: number };
53+
54+
type MyUnion = AA | BB;
55+
56+
const fn = (value: MyUnion) => {
57+
value.foo; // Error
58+
~~~
59+
!!! error TS2339: Property 'foo' does not exist on type 'MyUnion'.
60+
!!! error TS2339: Property 'foo' does not exist on type 'AA'.
61+
if ('foo' in value) {
62+
value.foo;
63+
}
64+
if (value.tag === 'B') {
65+
value.foo;
66+
}
67+
};
68+
69+
const fn2 = <T extends MyUnion>(value: T): MyUnion => {
70+
~~~~~~~
71+
!!! error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
72+
value.foo; // Error
73+
~~~
74+
!!! error TS2339: Property 'foo' does not exist on type 'MyUnion'.
75+
!!! error TS2339: Property 'foo' does not exist on type 'AA'.
76+
if ('foo' in value) {
77+
value.foo;
78+
}
79+
if (value.tag === 'B') {
80+
value.foo;
81+
}
82+
};
83+
84+
// Repro from #13995
85+
86+
type A1 = {
87+
testable: true
88+
doTest: () => void
89+
}
90+
type B1 = {
91+
testable: false
92+
};
93+
94+
type Union = A1 | B1
95+
96+
function notWorking<T extends Union>(object: T) {
97+
if (!object.testable) return;
98+
object.doTest();
99+
}
100+
101+
// Repro from #42939
102+
103+
interface A {
104+
a: number | null;
105+
};
106+
107+
function get<K extends keyof A>(key: K, obj: A): number {
108+
const value = obj[key];
109+
if (value !== null) {
110+
return value;
111+
}
112+
return 0;
113+
};
114+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
//// [controlFlowGenericTypes.ts]
2+
function f1<T extends string | undefined>(x: T, y: { a: T }, z: [T]): string {
3+
if (x) {
4+
x;
5+
x.length;
6+
return x;
7+
}
8+
if (y.a) {
9+
y.a.length;
10+
return y.a;
11+
}
12+
if (z[0]) {
13+
z[0].length;
14+
return z[0];
15+
}
16+
return "hello";
17+
}
18+
19+
function f2<T>(x: Extract<T, string | undefined> | null): string {
20+
if (x) {
21+
x;
22+
x.length;
23+
return x;
24+
}
25+
return "hello";
26+
}
27+
28+
// Repro from #13995
29+
30+
declare function takeA(val: 'A'): void;
31+
export function bounceAndTakeIfA<AB extends 'A' | 'B'>(value: AB): AB {
32+
if (value === 'A') {
33+
takeA(value);
34+
return value;
35+
}
36+
else {
37+
return value;
38+
}
39+
}
40+
41+
// Repro from #13995
42+
43+
type Common = { id: number };
44+
type AA = { tag: 'A', id: number };
45+
type BB = { tag: 'B', id: number, foo: number };
46+
47+
type MyUnion = AA | BB;
48+
49+
const fn = (value: MyUnion) => {
50+
value.foo; // Error
51+
if ('foo' in value) {
52+
value.foo;
53+
}
54+
if (value.tag === 'B') {
55+
value.foo;
56+
}
57+
};
58+
59+
const fn2 = <T extends MyUnion>(value: T): MyUnion => {
60+
value.foo; // Error
61+
if ('foo' in value) {
62+
value.foo;
63+
}
64+
if (value.tag === 'B') {
65+
value.foo;
66+
}
67+
};
68+
69+
// Repro from #13995
70+
71+
type A1 = {
72+
testable: true
73+
doTest: () => void
74+
}
75+
type B1 = {
76+
testable: false
77+
};
78+
79+
type Union = A1 | B1
80+
81+
function notWorking<T extends Union>(object: T) {
82+
if (!object.testable) return;
83+
object.doTest();
84+
}
85+
86+
// Repro from #42939
87+
88+
interface A {
89+
a: number | null;
90+
};
91+
92+
function get<K extends keyof A>(key: K, obj: A): number {
93+
const value = obj[key];
94+
if (value !== null) {
95+
return value;
96+
}
97+
return 0;
98+
};
99+
100+
101+
//// [controlFlowGenericTypes.js]
102+
"use strict";
103+
exports.__esModule = true;
104+
exports.bounceAndTakeIfA = void 0;
105+
function f1(x, y, z) {
106+
if (x) {
107+
x;
108+
x.length;
109+
return x;
110+
}
111+
if (y.a) {
112+
y.a.length;
113+
return y.a;
114+
}
115+
if (z[0]) {
116+
z[0].length;
117+
return z[0];
118+
}
119+
return "hello";
120+
}
121+
function f2(x) {
122+
if (x) {
123+
x;
124+
x.length;
125+
return x;
126+
}
127+
return "hello";
128+
}
129+
function bounceAndTakeIfA(value) {
130+
if (value === 'A') {
131+
takeA(value);
132+
return value;
133+
}
134+
else {
135+
return value;
136+
}
137+
}
138+
exports.bounceAndTakeIfA = bounceAndTakeIfA;
139+
var fn = function (value) {
140+
value.foo; // Error
141+
if ('foo' in value) {
142+
value.foo;
143+
}
144+
if (value.tag === 'B') {
145+
value.foo;
146+
}
147+
};
148+
var fn2 = function (value) {
149+
value.foo; // Error
150+
if ('foo' in value) {
151+
value.foo;
152+
}
153+
if (value.tag === 'B') {
154+
value.foo;
155+
}
156+
};
157+
function notWorking(object) {
158+
if (!object.testable)
159+
return;
160+
object.doTest();
161+
}
162+
;
163+
function get(key, obj) {
164+
var value = obj[key];
165+
if (value !== null) {
166+
return value;
167+
}
168+
return 0;
169+
}
170+
;

0 commit comments

Comments
 (0)