-
-
Notifications
You must be signed in to change notification settings - Fork 67
/
index.d.ts
80 lines (72 loc) · 3.16 KB
/
index.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
/* eslint-disable @typescript-eslint/ban-types */
type LastArrayElement<T extends readonly unknown[]> = T extends [...any, infer L]
? L
: never;
type DropLastArrayElement<T extends readonly unknown[]> = T extends [...(infer U), unknown]
? U
: [];
type StringEndsWith<S, X extends string> = S extends `${infer _}${X}` ? true : false;
type Options<Includes extends readonly unknown[], Excludes extends readonly unknown[], MultiArgs extends boolean = false, ErrorFirst extends boolean = true, ExcludeMain extends boolean = false> = {
multiArgs?: MultiArgs;
include?: Includes;
exclude?: Excludes;
errorFirst?: ErrorFirst;
promiseModule?: PromiseConstructor;
excludeMain?: ExcludeMain;
};
type InternalOptions<Includes extends readonly unknown[], Excludes extends readonly unknown[], MultiArgs extends boolean = false, ErrorFirst extends boolean = true> = {
multiArgs: MultiArgs;
include: Includes;
exclude: Excludes;
errorFirst: ErrorFirst;
};
type Promisify<Args extends readonly unknown[], GenericOptions extends InternalOptions<readonly unknown[], readonly unknown[], boolean, boolean>> = (
...args: DropLastArrayElement<Args>
) =>
LastArrayElement<Args> extends (...arguments_: any) => any
// For single-argument functions when errorFirst: true we just return Promise<unknown> as it will always reject.
? Parameters<LastArrayElement<Args>> extends [infer SingleCallbackArg] ? GenericOptions extends {errorFirst: true} ? Promise<unknown> : Promise<SingleCallbackArg>
: Promise<
GenericOptions extends {multiArgs: false}
? LastArrayElement<Parameters<LastArrayElement<Args>>>
: Parameters<LastArrayElement<Args>>
>
// Functions without a callback will return a promise that never settles. We model this as Promise<unknown>
: Promise<unknown>;
type PromisifyModule<
Module extends Record<string, any>,
MultiArgs extends boolean,
ErrorFirst extends boolean,
Includes extends ReadonlyArray<keyof Module>,
Excludes extends ReadonlyArray<keyof Module>,
> = {
[K in keyof Module]: Module[K] extends (...arguments_: infer Arguments) => any
? K extends Includes[number]
? Promisify<Arguments, InternalOptions<Includes, Excludes, MultiArgs>>
: K extends Excludes[number]
? Module[K]
: StringEndsWith<K, 'Sync' | 'Stream'> extends true
? Module[K]
: Promisify<Arguments, InternalOptions<Includes, Excludes, MultiArgs, ErrorFirst>>
: Module[K];
};
export default function pify<
FirstArgument,
Arguments extends readonly unknown[],
MultiArgs extends boolean = false,
ErrorFirst extends boolean = true,
>(
input: (argument: FirstArgument, ...arguments_: Arguments) => any,
options?: Options<[], [], MultiArgs, ErrorFirst>
): Promisify<[FirstArgument, ...Arguments], InternalOptions<[], [], MultiArgs, ErrorFirst>>;
export default function pify<
Module extends Record<string, any>,
Includes extends ReadonlyArray<keyof Module> = [],
Excludes extends ReadonlyArray<keyof Module> = [],
MultiArgs extends boolean = false,
ErrorFirst extends boolean = true,
>(
// eslint-disable-next-line unicorn/prefer-module
module: Module,
options?: Options<Includes, Excludes, MultiArgs, ErrorFirst, true>
): PromisifyModule<Module, MultiArgs, ErrorFirst, Includes, Excludes>;