To achieve this functionality, you can utilize generic parameters for both the argument-array and the result type. By implementing something similar to the code snippet below:
function createResolver<Args extends unknown[], Res>(
resolverFn: (...args: Args) => Res
): (...args: Args) => Res {
return (...args: Args) => {
// Additional logic can be added here...
return resolverFn(...args);
};
}
However, keep in mind that the example with the resolversMap
may not work as expected because the overallRankingPlacement
function returns a promise while the argument of createResolver
does not. To resolve this issue, you can either remove Promise
from the return type or pass an asynchronous function to createResolver
for aligning the types correctly.
If your goal is to have a version of createResolver
that returns an async function, you can modify the function as follows:
function createAsyncResolver<Args extends unknown[], Res>(
resolverFn: (...args: Args) => Res
): (...args: Args) => Promise<Res> {
return async (...args: Args) => {
// Additional async logic can be included here...
return resolverFn(...args);
};
}
This updated version will operate seamlessly with your provided resolversMap
.
It's important to note that wrapping functions in this manner might not handle overloaded functions effectively. The wrapped function may retain only the last overload, resulting in situations like:
const unfortunatelyNotOverloaded = createResolver(overloaded)
const ok = unfortunatelyNotOverloaded('ok') // inferred type: string
const fail = unfortunatelyNotOverloaded(1)
// ERROR: Argument of type 'number' is not assignable to parameter of type 'string'.
At present, there doesn't seem to be a workaround for this limitation, and it might not be supported in the future.
TypeScript playground