forked from microsoft/TypeScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspreadTupleUnionDistribution.js
More file actions
97 lines (82 loc) · 4.77 KB
/
spreadTupleUnionDistribution.js
File metadata and controls
97 lines (82 loc) · 4.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//// [tests/cases/conformance/types/spread/spreadTupleUnionDistribution.ts] ////
//// [spreadTupleUnionDistribution.ts]
// Repro from #62812
// Spread operator fails to distribute over union when recursive type call is inlined instead of aliased
type CrossProduct<Union, Counter extends unknown[]> =
Counter extends [infer Zero, ...infer Rest]
? (Union extends infer Member
? [Member, ...CrossProduct<Union, Rest>]
: never)
: [];
// Basic test - this works
let test1: CrossProduct<number | string, [undefined]>; // [string] | [number]
type Depth1 = CrossProduct<number | string, [undefined]> // [string] | [number]
// With alias - this should work and give full cross product
let test2: (number | string extends infer Union ? (Union extends unknown ? [Union, ...Depth1]: never) : never);
// Expected: [string, string] | [number, number] | [string, number] | [number, string]
// With inlined type - this should also work but currently doesn't distribute properly
let test3: (number | string extends infer Union ? (Union extends unknown ? [Union, ...CrossProduct<number | string, [undefined]>]: never) : never);
// Expected: [string, string] | [number, number] | [string, number] | [number, string]
// Actual (bug): [string, string] | [number, number]
// With literal union - this works
let test4: (number | string extends infer Union ? (Union extends unknown ? [Union, ...([string] | [number])]: never) : never);
// Expected: [string, string] | [number, number] | [string, number] | [number, string]
// Test that the types are actually correct by checking assignability
type Expected = [string, string] | [number, number] | [string, number] | [number, string];
// These should all be true (no error)
type Test1Check = Expected extends typeof test2 ? true : false;
type Test2Check = typeof test2 extends Expected ? true : false;
// If the bug is fixed, these will also be true (no error)
type Test3Check = Expected extends typeof test3 ? true : false;
type Test4Check = typeof test3 extends Expected ? true : false;
type Test5Check = Expected extends typeof test4 ? true : false;
type Test6Check = typeof test4 extends Expected ? true : false;
// Force an error if checks fail
const _check1: Test1Check = true;
const _check2: Test2Check = true;
const _check3: Test3Check = true; // This will error if bug exists
const _check4: Test4Check = true; // This will error if bug exists
const _check5: Test5Check = true;
const _check6: Test6Check = true;
//// [spreadTupleUnionDistribution.js]
"use strict";
// Repro from #62812
// Spread operator fails to distribute over union when recursive type call is inlined instead of aliased
// Basic test - this works
var test1; // [string] | [number]
// With alias - this should work and give full cross product
var test2;
// Expected: [string, string] | [number, number] | [string, number] | [number, string]
// With inlined type - this should also work but currently doesn't distribute properly
var test3;
// Expected: [string, string] | [number, number] | [string, number] | [number, string]
// Actual (bug): [string, string] | [number, number]
// With literal union - this works
var test4;
// Force an error if checks fail
var _check1 = true;
var _check2 = true;
var _check3 = true; // This will error if bug exists
var _check4 = true; // This will error if bug exists
var _check5 = true;
var _check6 = true;
//// [spreadTupleUnionDistribution.d.ts]
type CrossProduct<Union, Counter extends unknown[]> = Counter extends [infer Zero, ...infer Rest] ? (Union extends infer Member ? [Member, ...CrossProduct<Union, Rest>] : never) : [];
declare let test1: CrossProduct<number | string, [undefined]>;
type Depth1 = CrossProduct<number | string, [undefined]>;
declare let test2: (number | string extends infer Union ? (Union extends unknown ? [Union, ...Depth1] : never) : never);
declare let test3: (number | string extends infer Union ? (Union extends unknown ? [Union, ...CrossProduct<number | string, [undefined]>] : never) : never);
declare let test4: (number | string extends infer Union ? (Union extends unknown ? [Union, ...([string] | [number])] : never) : never);
type Expected = [string, string] | [number, number] | [string, number] | [number, string];
type Test1Check = Expected extends typeof test2 ? true : false;
type Test2Check = typeof test2 extends Expected ? true : false;
type Test3Check = Expected extends typeof test3 ? true : false;
type Test4Check = typeof test3 extends Expected ? true : false;
type Test5Check = Expected extends typeof test4 ? true : false;
type Test6Check = typeof test4 extends Expected ? true : false;
declare const _check1: Test1Check;
declare const _check2: Test2Check;
declare const _check3: Test3Check;
declare const _check4: Test4Check;
declare const _check5: Test5Check;
declare const _check6: Test6Check;