Skip to content

Commit 56b4f68

Browse files
committed
Add regression test
1 parent 2ce1eb9 commit 56b4f68

5 files changed

+488
-0
lines changed
Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts(314,5): error TS7022: 'value1' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
2+
tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts(314,5): error TS7031: Binding element 'value1' implicitly has an 'any' type.
3+
4+
5+
==== tests/cases/conformance/controlFlow/dependentDestructuredVariables.ts (2 errors) ====
6+
type Action =
7+
| { kind: 'A', payload: number }
8+
| { kind: 'B', payload: string };
9+
10+
function f10({ kind, payload }: Action) {
11+
if (kind === 'A') {
12+
payload.toFixed();
13+
}
14+
if (kind === 'B') {
15+
payload.toUpperCase();
16+
}
17+
}
18+
19+
function f11(action: Action) {
20+
const { kind, payload } = action;
21+
if (kind === 'A') {
22+
payload.toFixed();
23+
}
24+
if (kind === 'B') {
25+
payload.toUpperCase();
26+
}
27+
}
28+
29+
function f12({ kind, payload }: Action) {
30+
switch (kind) {
31+
case 'A':
32+
payload.toFixed();
33+
break;
34+
case 'B':
35+
payload.toUpperCase();
36+
break;
37+
default:
38+
payload; // never
39+
}
40+
}
41+
42+
type Action2 =
43+
| { kind: 'A', payload: number | undefined }
44+
| { kind: 'B', payload: string | undefined };
45+
46+
function f20({ kind, payload }: Action2) {
47+
if (payload) {
48+
if (kind === 'A') {
49+
payload.toFixed();
50+
}
51+
if (kind === 'B') {
52+
payload.toUpperCase();
53+
}
54+
}
55+
}
56+
57+
function f21(action: Action2) {
58+
const { kind, payload } = action;
59+
if (payload) {
60+
if (kind === 'A') {
61+
payload.toFixed();
62+
}
63+
if (kind === 'B') {
64+
payload.toUpperCase();
65+
}
66+
}
67+
}
68+
69+
function f22(action: Action2) {
70+
if (action.payload) {
71+
const { kind, payload } = action;
72+
if (kind === 'A') {
73+
payload.toFixed();
74+
}
75+
if (kind === 'B') {
76+
payload.toUpperCase();
77+
}
78+
}
79+
}
80+
81+
function f23({ kind, payload }: Action2) {
82+
if (payload) {
83+
switch (kind) {
84+
case 'A':
85+
payload.toFixed();
86+
break;
87+
case 'B':
88+
payload.toUpperCase();
89+
break;
90+
default:
91+
payload; // never
92+
}
93+
}
94+
}
95+
96+
type Foo =
97+
| { kind: 'A', isA: true }
98+
| { kind: 'B', isA: false }
99+
| { kind: 'C', isA: false };
100+
101+
function f30({ kind, isA }: Foo) {
102+
if (kind === 'A') {
103+
isA; // true
104+
}
105+
if (kind === 'B') {
106+
isA; // false
107+
}
108+
if (kind === 'C') {
109+
isA; // false
110+
}
111+
if (isA) {
112+
kind; // 'A'
113+
}
114+
else {
115+
kind; // 'B' | 'C'
116+
}
117+
}
118+
119+
type Args = ['A', number] | ['B', string]
120+
121+
function f40(...[kind, data]: Args) {
122+
if (kind === 'A') {
123+
data.toFixed();
124+
}
125+
if (kind === 'B') {
126+
data.toUpperCase();
127+
}
128+
}
129+
130+
// Repro from #35283
131+
132+
interface A<T> { variant: 'a', value: T }
133+
134+
interface B<T> { variant: 'b', value: Array<T> }
135+
136+
type AB<T> = A<T> | B<T>;
137+
138+
declare function printValue<T>(t: T): void;
139+
140+
declare function printValueList<T>(t: Array<T>): void;
141+
142+
function unrefined1<T>(ab: AB<T>): void {
143+
const { variant, value } = ab;
144+
if (variant === 'a') {
145+
printValue<T>(value);
146+
}
147+
else {
148+
printValueList<T>(value);
149+
}
150+
}
151+
152+
// Repro from #38020
153+
154+
type Action3 =
155+
| {type: 'add', payload: { toAdd: number } }
156+
| {type: 'remove', payload: { toRemove: number } };
157+
158+
const reducerBroken = (state: number, { type, payload }: Action3) => {
159+
switch (type) {
160+
case 'add':
161+
return state + payload.toAdd;
162+
case 'remove':
163+
return state - payload.toRemove;
164+
}
165+
}
166+
167+
// Repro from #46143
168+
169+
declare var it: Iterator<number>;
170+
const { value, done } = it.next();
171+
if (!done) {
172+
value; // number
173+
}
174+
175+
// Repro from #46658
176+
177+
declare function f50(cb: (...args: Args) => void): void
178+
179+
f50((kind, data) => {
180+
if (kind === 'A') {
181+
data.toFixed();
182+
}
183+
if (kind === 'B') {
184+
data.toUpperCase();
185+
}
186+
});
187+
188+
const f51: (...args: ['A', number] | ['B', string]) => void = (kind, payload) => {
189+
if (kind === 'A') {
190+
payload.toFixed();
191+
}
192+
if (kind === 'B') {
193+
payload.toUpperCase();
194+
}
195+
};
196+
197+
const f52: (...args: ['A', number] | ['B']) => void = (kind, payload?) => {
198+
if (kind === 'A') {
199+
payload.toFixed();
200+
}
201+
else {
202+
payload; // undefined
203+
}
204+
};
205+
206+
declare function readFile(path: string, callback: (...args: [err: null, data: unknown[]] | [err: Error, data: undefined]) => void): void;
207+
208+
readFile('hello', (err, data) => {
209+
if (err === null) {
210+
data.length;
211+
}
212+
else {
213+
err.message;
214+
}
215+
});
216+
217+
type ReducerArgs = ["add", { a: number, b: number }] | ["concat", { firstArr: any[], secondArr: any[] }];
218+
219+
const reducer: (...args: ReducerArgs) => void = (op, args) => {
220+
switch (op) {
221+
case "add":
222+
console.log(args.a + args.b);
223+
break;
224+
case "concat":
225+
console.log(args.firstArr.concat(args.secondArr));
226+
break;
227+
}
228+
}
229+
230+
reducer("add", { a: 1, b: 3 });
231+
reducer("concat", { firstArr: [1, 2], secondArr: [3, 4] });
232+
233+
// repro from https://github.com/microsoft/TypeScript/pull/47190#issuecomment-1057603588
234+
235+
type FooMethod = {
236+
method(...args:
237+
[type: "str", cb: (e: string) => void] |
238+
[type: "num", cb: (e: number) => void]
239+
): void;
240+
}
241+
242+
let fooM: FooMethod = {
243+
method(type, cb) {
244+
if (type == 'num') {
245+
cb(123)
246+
} else {
247+
cb("abc")
248+
}
249+
}
250+
};
251+
252+
type FooAsyncMethod = {
253+
method(...args:
254+
[type: "str", cb: (e: string) => void] |
255+
[type: "num", cb: (e: number) => void]
256+
): Promise<any>;
257+
}
258+
259+
let fooAsyncM: FooAsyncMethod = {
260+
async method(type, cb) {
261+
if (type == 'num') {
262+
cb(123)
263+
} else {
264+
cb("abc")
265+
}
266+
}
267+
};
268+
269+
type FooGenMethod = {
270+
method(...args:
271+
[type: "str", cb: (e: string) => void] |
272+
[type: "num", cb: (e: number) => void]
273+
): Generator<any, any, any>;
274+
}
275+
276+
let fooGenM: FooGenMethod = {
277+
*method(type, cb) {
278+
if (type == 'num') {
279+
cb(123)
280+
} else {
281+
cb("abc")
282+
}
283+
}
284+
};
285+
286+
type FooAsyncGenMethod = {
287+
method(...args:
288+
[type: "str", cb: (e: string) => void] |
289+
[type: "num", cb: (e: number) => void]
290+
): AsyncGenerator<any, any, any>;
291+
}
292+
293+
let fooAsyncGenM: FooAsyncGenMethod = {
294+
async *method(type, cb) {
295+
if (type == 'num') {
296+
cb(123)
297+
} else {
298+
cb("abc")
299+
}
300+
}
301+
};
302+
303+
// Repro from #48345
304+
305+
type Func = <T extends ["a", number] | ["b", string]>(...args: T) => void;
306+
307+
const f60: Func = (kind, payload) => {
308+
if (kind === "a") {
309+
payload.toFixed(); // error
310+
}
311+
if (kind === "b") {
312+
payload.toUpperCase(); // error
313+
}
314+
};
315+
316+
// Repro from #48902
317+
318+
function foo({
319+
value1,
320+
~~~~~~
321+
!!! error TS7022: 'value1' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
322+
~~~~~~
323+
!!! error TS7031: Binding element 'value1' implicitly has an 'any' type.
324+
test1 = value1.test1,
325+
test2 = value1.test2,
326+
test3 = value1.test3,
327+
test4 = value1.test4,
328+
test5 = value1.test5,
329+
test6 = value1.test6,
330+
test7 = value1.test7,
331+
test8 = value1.test8,
332+
test9 = value1.test9
333+
}) {}
334+

tests/baselines/reference/dependentDestructuredVariables.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,21 @@ const f60: Func = (kind, payload) => {
308308
payload.toUpperCase(); // error
309309
}
310310
};
311+
312+
// Repro from #48902
313+
314+
function foo({
315+
value1,
316+
test1 = value1.test1,
317+
test2 = value1.test2,
318+
test3 = value1.test3,
319+
test4 = value1.test4,
320+
test5 = value1.test5,
321+
test6 = value1.test6,
322+
test7 = value1.test7,
323+
test8 = value1.test8,
324+
test9 = value1.test9
325+
}) {}
311326

312327

313328
//// [dependentDestructuredVariables.js]
@@ -550,6 +565,8 @@ const f60 = (kind, payload) => {
550565
payload.toUpperCase(); // error
551566
}
552567
};
568+
// Repro from #48902
569+
function foo({ value1, test1 = value1.test1, test2 = value1.test2, test3 = value1.test3, test4 = value1.test4, test5 = value1.test5, test6 = value1.test6, test7 = value1.test7, test8 = value1.test8, test9 = value1.test9 }) { }
553570

554571

555572
//// [dependentDestructuredVariables.d.ts]
@@ -667,3 +684,15 @@ declare type FooAsyncGenMethod = {
667684
declare let fooAsyncGenM: FooAsyncGenMethod;
668685
declare type Func = <T extends ["a", number] | ["b", string]>(...args: T) => void;
669686
declare const f60: Func;
687+
declare function foo({ value1, test1, test2, test3, test4, test5, test6, test7, test8, test9 }: {
688+
value1: any;
689+
test1?: any;
690+
test2?: any;
691+
test3?: any;
692+
test4?: any;
693+
test5?: any;
694+
test6?: any;
695+
test7?: any;
696+
test8?: any;
697+
test9?: any;
698+
}): void;

0 commit comments

Comments
 (0)