Problem
How can I expose an overloading implementation signature correctly?
Example
Building off of this question:
interface MyMap<T> {
[id: string]: T;
}
type Options = {
asObject?: boolean,
other?: Function
testing?: number
};
function get(options: { asObject: true, other?: Function, testing?:number }): MyMap<any>;
function get(options: { asObject?: false, other?: Function, testing?:number }): number[];
function get(): any[];
function get(options: Options = { asObject: false }): any[] | MyMap<any> {
if (options?.asObject) return {} as MyMap<any>;
return [];
}
How can I wrap this function but retain the possible return types depending on the options argument?
For example:
function wrapFunction(arg1 arg2, options) {
// do something with arg1 and arg2
return get(options)
}
Depending on the value set for options in the wrapFunction method, the return type would be based on the return type of get with that same value.
ie:
const g = wrapFunction(1,2, {asObject: true})
// Should return the same thing as get({asObject:true})
Attempted Solutions
I could simply rewrite a new signature for the wrapFunction, but this would be quite verbose, especially if I have many types of wrapFunctions that follow the same pattern of having a nested get call.
One suggestion was to type cast the wrapFunction as typeof get but this removes the ability to modify the parameters list of wrapFunction.
This might be related.
const b = g({ asObject: true })is going to beany[] | MyMap<any>, not just theMyMap<any>from the first signature.