Open Roaders opened 5 years ago
You can do this today in TypeScript:
// make a tuple into a tuple whose elements are **all** optional:
type AllOptional<T extends unknown[]> = { [k in keyof T]?: T[k] }
type RestOptional<T extends unknown[]> =
((...xs: T) => unknown) extends ((h: infer Head, ...ts: infer Tail) => any)
? ((h: Head, ...ts: AllOptional<Tail> ) => void) extends (...a: infer A) => any ? A : never
: never;
You can use it like this:
type Example = RestOptional<[number, string, number>];
// type Example = [number, (string | undefined)?, (number | undefined)?]
That's great, thank you very much.
To make it a bit easier to understand (for me!) I refactored it a bit:
type AllOptional<T extends unknown[]> = { [k in keyof T]?: T[k] }
type CombineHeadTail<Head, Tail extends unknown[]> = ((h: Head, ...ts: AllOptional<Tail> ) => void) extends (...a: infer A) => any ? A : never
type TailOptional<T extends unknown[]> =
((...allParams: T) => unknown) extends ((head: infer Head, ...tail: infer Tail) => any) ?
CombineHeadTail<Head, Tail> : never;
I still can't understand why this works though. ((...allParams: T) => unknown) extends ((head: infer Head, ...tail: infer Tail) => any)
implies that T has to be function params but in your example it obviously works when used on any tuple.
I realised after I posted this issue that the actual difficult bit about what I am trying to achieve is the return type.
If I have this function:
function myFunction(one: string, two: number, three: boolean): ReturnType{}
then I want my curry function to have the following arguments (this I can now achieve):
curry(myFunction, one: string, two?: number, three?: boolean)
but I want the return type of this function to be based on the number of arguments filled in:
curry(myFunction, one: string) => (two: number, three: boolean) => ReturnType;
curry(myFunction, one: string, two: number) => (three: boolean) => ReturnType;
curry(myFunction, one: string, two: number, three: boolean) => () => ReturnType;
this is easy to achieve with function overrides but not in a generic, mapped (magic) way!
Thanks for your help
Search Terms
mapped tuples index
Suggestion
I want to be able to create a tuple from function parameters and have all elements in the tuple optional other than the firstK
Use Cases
I am trying to create a curry implementation that allows you to curry any number of parameters. The first parameter must be specified but all other params are optional. Would be good to be able to remove the last param as well.
Examples
something along the lines of
The syntax will need some work hopefully the intended functionality is clear.
Checklist
My suggestion meets these guidelines: