|
| 1 | +// This file contains some utility types that either can't be expressed in |
| 2 | +// JSDoc syntax or that result in a different behaviour when typed in JSDoc. |
| 3 | + |
| 4 | +/** |
| 5 | + * Utility type that takes IPFS Core API function type (with 0 to 4 arguments |
| 6 | + * & last **optional** `options` parameter) and derives a function type with |
| 7 | + * `options` parameter extended with given `Extra` options. |
| 8 | + * |
| 9 | + * **Caution**: API Functions with more than for arguments ahead of `options` |
| 10 | + * will result to `never` type. API function that does not take `options` will |
| 11 | + * result in function whose last argument is extended with `Extra` which would |
| 12 | + * be an error. |
| 13 | + */ |
| 14 | +// This is typed in TS file because otherwise TS unifies on the first parameter |
| 15 | +// regardless of number of parameters function has. |
| 16 | +export type APIWithExtraOptions<API extends (...args: any[]) => any, Extra> = |
| 17 | + (...args: WithExtendedOptions<Parameters<API>, Extra>) => ReturnType<API> |
| 18 | + |
| 19 | +type End = never[] |
| 20 | +type WithExtendedOptions<Params, Ext> = Params extends [...End] |
| 21 | + ? [] |
| 22 | + // (options?: Options) -> (options?: Options & Ext) |
| 23 | + : Params extends [options?: infer Options, ...end: End] |
| 24 | + ? [options?: Options & Ext] |
| 25 | + // (a: A1, options?: Options) -> (a1: A1, options?: Options & Ext) |
| 26 | + : Params extends [a1: infer A1, options?: infer Options, ...end: End] |
| 27 | + ? [a1: A1, options?: Options & Ext] |
| 28 | + // (a1?: A1, options?: Options) -> (a1?: A1, options?: Options & Ext) |
| 29 | + : Params extends [a1?: infer A1, options?: infer Options, ...end: End] |
| 30 | + ? [a1?: A1, options?: Options & Ext] |
| 31 | + // (a1: A1, a2: A2, options?: Options) -> (a1: A1, a2: A2 options?: Options & Ext) |
| 32 | + : Params extends [a1: infer A1, a2: infer A2, options?: infer Options, ...end: End] |
| 33 | + ? [a1: A1, a2: A2, options?: Options & Ext] |
| 34 | + // (a1: A1, a2?: A2, options?: Options) -> (a1: A1, a2?: A2 options?: Options & Ext) |
| 35 | + : Params extends [a1: infer A1, a2?: infer A2, options?: infer Options, ...end: End] |
| 36 | + ? [a1: A1, a2?: A2, options?: Options & Ext] |
| 37 | + // (a1: A1, a2?: A2, options?: Options) -> (a1: A1, a2?: A2 options?: Options & Ext) |
| 38 | + : Params extends [a1?: infer A1, a2?: infer A2, options?: infer Options, ...end: End] |
| 39 | + ? [a1?: A1, a2?: A2, options?: Options & Ext] |
| 40 | + // (a1: A1, a2: A2, a3:A3 options?: Options) -> (a1: A1, a2: A2, a3:A3, options?: Options & Ext) |
| 41 | + : Params extends [a1: infer A1, a2: infer A2, a3:infer A3, options?: infer Options, ...end: End] |
| 42 | + ? [a1: A1, a2: A2, a3: A3, options?: Options & Ext] |
| 43 | + // (a1: A1, a2: A2, a3?:A3 options?: Options) -> (a1: A1, a2: A2, a3?:A3, options?: Options & Ext) |
| 44 | + : Params extends [a1: infer A1, a2:infer A2, a3?: infer A3, options?: infer Options, ...end: End] |
| 45 | + ? [a1: A1, a2: A2, a3?: A3, options?: Options & Ext] |
| 46 | + // (a1: A1, a2?: A2, a3?:A3 options?: Options) -> (a1: A1, a2?: A2, a3?:A3, options?: Options & Ext) |
| 47 | + : Params extends [a1: infer A1, a2?: infer A2, a3?: infer A3, options?: infer Options, ...end: End] |
| 48 | + ? [a1: A1, a2?: A2, a3?: A3, options?: Options & Ext] |
| 49 | + // (a1?: A1, a2?: A2, a3?:A3 options?: Options) -> (a1?: A1, a2?: A2, a3?:A3, options?: Options & Ext) |
| 50 | + : Params extends [a1?: infer A1, a2?: infer A2, a3?: infer A3, options?: infer Options, ...end: End] |
| 51 | + ? [a1?: A1, a2?: A2, a3?: A3, options?: Options & Ext] |
| 52 | + : never |
| 53 | + |
| 54 | +export type APIMethodWithExtraOptions < |
| 55 | + API, |
| 56 | + Key extends keyof API, |
| 57 | + Extra |
| 58 | + > = API[Key] extends (...args: any[]) => any ? APIWithExtraOptions<API[Key], Extra> : never |
0 commit comments