-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtuple.d.ts
59 lines (52 loc) · 1.68 KB
/
tuple.d.ts
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
/**
* Create a tuple type of arbitrary length. Safe to consume in an `extends` clause.
* Do not do keyof on this.
*/
export type Tuple<ElementT, L extends number> = Array<ElementT> & {
0: ElementT;
length: L;
};
/**
* Add a member to the start of a tuple
*/
export type Unshift<TailT extends any[], FrontT> = ((
front: FrontT,
...rest: TailT
) => any) extends (...tuple: infer TupleT) => any
? TupleT
: never;
export type IsFinite<Tuple extends any[], Finite, Infinite> = {
empty: Finite;
nonEmpty: ((..._: Tuple) => any) extends (_: infer First, ..._1: infer Rest) => any
? IsFinite<Rest, Finite, Infinite>
: never;
infinite: Infinite;
}[Tuple extends []
? "empty"
: Tuple extends (infer Element)[]
? Element[] extends Tuple
? "infinite"
: "nonEmpty"
: never];
type Tail<T extends any[]> = ((...args: T) => any) extends (f: any, ...r: infer R) => any ? R : [];
type Last<T extends any[]> = {
last: T[0];
continue: Last<Tail<T>>;
}[T[1] extends undefined ? "last" : "continue"];
type Reverse<T extends any[], Accumulator extends any[] = []> = {
done: Accumulator;
continue: ((...x: T) => any) extends (y: infer First, ...ys: infer Next) => any
? Reverse<Next, Unshift<Accumulator, First>>
: never;
}[T extends [any, ...any[]] ? "continue" : "done"];
type Init<T extends any[]> = Reverse<Tail<Reverse<T>>>;
export type Concat<Left extends any[], Right extends any[]> = {
emptyLeft: Right;
singleLeft: Left extends [infer SoleElement] ? Unshift<Right, SoleElement> : never;
multiLeft: Concat<Init<Left>, Unshift<Right, Last<Left>>>;
infiniteLeft: never;
}[Left extends []
? "emptyLeft"
: Left extends [any]
? "singleLeft"
: IsFinite<Left, "multiLeft", "infiniteLeft">];