I'm trying to author a typesafe version of the classic promisify function. See my playground link here.
Node.js style callbacks generally have the form of (value?: ValueType, err?: ErrorType). Of course, they can also have an inner variadic form, such as (a?: A, b?: B, ..., n?: N, err?: Error). Covering the first form is easy. Covering the latter, I've found, is difficult. Why?
Well, I'm finding that type inference doesn't work well with optional arguments.
- First, to get the parameters of the node callback, I used
Parameters<MyCallbackType>, - Second, I try and get all inferred callback params up to last param, omitting the the
err?: Errorarg. I'm calling the slice of the array that includes everything but the tailBody, and defining it as:export type Body<T> = T extends [...infer B, infer _TailEl] ? B : never;
But... Body<T> doesn't work great when there are optional items in the tuple type. The problemo is that arg n?: N and err?: Error from Parameters do not appear to be being partitioned/considered in the infer, thus my conditional type lookup fails, and I'm out-of-luck.
My hack has been to Required wrap Parameters<...>, of which then I can successfully get the Body of the callback, and nicely reflect back a clean callback signature to the return value of promisify(fn)(args) => Promise<WellTypedTupleArgsFromCallback>.
One big exception--WellTypedTupleArgsFromCallback is now a tuple where everything is guaranteed because of the Required, which is a dishonest type.
This is very easy to see at work in the attached playground, and has some tests to show what is correct/incorrect.
How can I correctly map the variadic callback Body with optional elements?