-
-
Notifications
You must be signed in to change notification settings - Fork 146
/
Curry.ts
121 lines (112 loc) 路 2.88 KB
/
Curry.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
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import {Pos} from '../Iteration/Pos'
import {Concat} from '../List/Concat'
import {Length} from '../List/Length'
import {Next} from '../Iteration/Next'
import {Cast} from '../Any/Cast'
import {Parameters} from './Parameters'
import {Return} from './Return'
import {IterationOf} from '../Iteration/IterationOf'
import {Iteration} from '../Iteration/Iteration'
import {NonNullableFlat} from '../Object/NonNullable'
import {x} from '../Any/x'
import {List} from '../List/List'
import {Function} from './Function'
import {Extends} from '../Any/Extends'
import {Tail} from '../List/Tail'
import {RequiredKeys} from '../List/RequiredKeys'
/**
* @hidden
*/
type _SplitParams<P extends List, PSplit extends List[] = [], PRest extends List = Tail<P>> = {
0: P extends [...infer A, ...PRest]
? _SplitParams<Tail<P>, [...PSplit, A], Tail<PRest>>
: never
1: PSplit
2: P[number][][]
}[
number extends Length<P>
? 2
: P extends []
? 1
: 0
]
/**
* Splits tuples to preserve their labels
* @hidden
*/
type SplitParams<P extends List> =
_SplitParams<P> extends infer X
? Cast<X, List[]>
: never
/**
* @hidden
*/
type _JoinParams<PSplit extends List[], L extends List = []> = {
0: _JoinParams<Tail<PSplit>, [...L, ...PSplit[0]]>
1: L
2: PSplit[number][]
}[
number extends Length<PSplit>
? 2
: PSplit extends []
? 1
: 0
]
/**
* Undoes the job of [[SplitParams]]
* @hidden
*/
type JoinParams<P extends List[]> =
_JoinParams<P> extends infer X
? Cast<X, List>
: never
/**
* @hidden
*/
type GapOf<L1 extends List, L2 extends List[], LN extends List, I extends Iteration> =
L1[Pos<I>] extends x
? Concat<LN, L2[Pos<I>]>
: LN
/**
* @hidden
*/
type _GapsOf<L1 extends List, L2 extends List[], LN extends List = [], L2D extends List[] = L2, I extends Iteration = IterationOf<0>> = {
0: _GapsOf<L1, L2, GapOf<L1, L2, LN, I>, Tail<L2D>, Next<I>>
1: Concat<LN, JoinParams<L2D>>
}[Extends<Pos<I>, Length<L1>>]
/**
* @hidden
*/
type GapsOf<L1 extends List, L2 extends List> =
_GapsOf<L1, SplitParams<L2>> extends infer X
? Cast<X, List>
: never
/**
* @hidden
*/
type Gaps<L extends List> = Cast<NonNullableFlat<{
[K in keyof L]?: L[K] | x
}>, List>
/**
* Curry a [[Function]]
* @param F to curry
* @returns [[Function]]
* @example
* ```ts
* import {F} from 'ts-toolbelt'
*
* /// If you are looking for creating types for `curry`
* /// It handles placeholders and variable arguments
* declare function curry<Fn extends F.Function>(fn: Fn): F.Curry<Fn>
* ```
*/
export type Curry<F extends Function> =
<
P extends Gaps<Parameters<F>>,
G extends List = GapsOf<P, Parameters<F>>,
R extends any = Return<F>
>(...p: Gaps<Parameters<F>> | P) =>
// handles optional parameters
RequiredKeys<G> extends never
? R
: Curry<(...p: G) => R>