Reputation: 39992
Is it possible to create a new function definition based on an existing one?
For example, I have a third-party library that has the following two functions:
declare function v1(s: string, t: string): string;
declare function v2(n: number): string;
I have a function that was written in JS but recently has been requested to add Typescript definitions. My function looks like the following:
function useId(version, ...args) {
return generators[version](...args);
}
What I would like to do is take the existing v1 and v2 declarations and use them in my own like so:
declare function useId(v: "v1", ...v1): string;
declare function useId(v: "v2", ...v2): string;
I have not been able to find any advanced typings that cover this specific need but wanted to check before taking a longer more verbose route to adding my function definitions (given they'll be duplicates with one new parameter out front).
Upvotes: 1
Views: 789
Reputation: 95614
As in the question "Is there ArgumentsType<T> like ReturnType<T> in Typescript?", you can use Parameters<T>
and ReturnType<T>
to refer to the parameters and return type of a known function T
. If you type the ...args
parameters with that type, it will include those parameters in your signature.
declare function useId(v: "v1", ...args: Parameters<typeof v1>):
ReturnType<typeof v1>;
declare function useId(v: "v2", ...args: Parameters<typeof v2>):
ReturnType<typeof v2>;
useId("v1", "s", "t");
useId("v2", 9001);
If you are doing this repeatedly, you can use a callable interface type to represent the overload. (It may otherwise be difficult to specify the overload as a union, as in the question Overloaded function type in typescript.) If you need to do this a lot, I imagine you could even use mapped types or other cleverness to represent the relationship between your wrapper and your original function(s).
interface WrapperInterface<
V1 extends (...args: any) => any,
V2 extends (...args: any) => any> {
(version: "v1", ...args: Parameters<V1>): ReturnType<V1>;
(version: "v2", ...args: Parameters<V2>): ReturnType<V2>;
}
declare const useId2: WrapperInterface<typeof v1, typeof v2>;
useId2("v1", "s", "t");
useId2("v2", 9001);
Upvotes: 2