/
mod.d.ts
109 lines (97 loc) · 2.85 KB
/
mod.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
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
type Primitives = number | boolean | string | symbol | bigint | undefined | null
type IsOpaque<T> = T extends object
? T extends Primitives
? true
: false
: false
type IsEmpty<T> = {} extends T ? true : false
type NonEmpty<T> = IsEmpty<T> extends true ? never : T
type PickNever<T> = Pick<
T,
{ [K in keyof T]: T[K] extends never ? K : never }[keyof T]
>
type ExcludeNever<T> = Exclude<T, NonEmpty<PickNever<T>>>
type DeepExtract<T, U> = IsOpaque<T> extends true
? Extract<T, U>
: T extends object
? U extends object
? Extract<
ExcludeNever<{
[K in keyof T]: K extends keyof U ? DeepExtract<T[K], U[K]> : T[K]
}>,
U
>
: never
: Extract<T, U>
type DeepExclude<T, U> = IsOpaque<T> extends true
? Exclude<T, U>
: T extends object
? U extends object
? Exclude<
ExcludeNever<{
[K in keyof T]: K extends keyof U ? DeepExclude<T[K], U[K]> : T[K]
}>,
U
>
: never
: Exclude<T, U>
interface Guard<Input, Type extends Input> {
(input: Input): input is Type
}
type Pattern<Input> =
| Guard<Input, Input>
| (Input extends number
? Input | NumberConstructor
: Input extends string
? Input | StringConstructor
: Input extends boolean
? Input | BooleanConstructor
: Input extends symbol
? Input | SymbolConstructor
: Input extends bigint
? Input | BigIntConstructor
: Input extends Primitives
? Input
: Input extends object
? { [K in keyof Input]?: Pattern<Input[K]> }
: never)
type Invert<Pattern> = Pattern extends Guard<infer _, infer P>
? P
: Pattern extends NumberConstructor
? number
: Pattern extends StringConstructor
? string
: Pattern extends BooleanConstructor
? boolean
: Pattern extends SymbolConstructor
? symbol
: Pattern extends BigIntConstructor
? bigint
: Pattern extends Primitives
? Pattern
: Pattern extends object
? { [K in keyof Pattern]: Invert<Pattern[K]> }
: never
interface NonExhaustive<_> {}
interface Match<Input, Next = Input, Output = never> {
with<P extends Pattern<Input>, O, I = Invert<P>, R = DeepExtract<Input, I>>(
pattern: P,
callback: (result: R) => O,
): Match<Exclude<Input, I>, DeepExclude<Next, I>, O | Output>
with<
P extends [Pattern<Input>, ...Pattern<Input>[]],
O,
I = Invert<P[number]>,
R = DeepExtract<Input, I>,
>(
...args: [...patterns: P, callback: (result: R) => O]
): Match<Exclude<Input, I>, DeepExclude<Next, I>, O | Output>
run(): [Next] extends [never] ? Output : Output | undefined
otherwise: [Next] extends [never]
? never
: <Fallback>(cb: (result: Next) => Fallback) => Output | Fallback
exhaustive: [Next] extends [never]
? (errorMessage: string) => Output
: NonExhaustive<Next>
}
export declare function match<Input>(input: Input): Match<Input>