I have a function called doesPromiseyThings
that wraps a thunk and returns its value inside a Promise. I want to create another wrapper that not only handles the creation of thunks, but also ensures the returned type is a Promise-wrapped version of the original.
The problem arises when passing in a function that already returns a Promise - TypeScript complains that the returned types end up being Promise<Promise<T>>
, which is not what I intended.
async function foo(param: number) {
return param;
}
function doesPromiseyThings<T>(fn: () => T): Promise<T> {
return Promise.resolve(fn());
}
function wrapper<T,U>(fn: (...args: T[]) => U) {
return (...args: T[]) => doesPromiseyThings(fn);
}
const wrappedFoo = wrapper(foo);
// (...args: number[]) => Promise<Promise<number>>
const output = wrappedFoo(1);
// Promise<Promise<number>>
I attempted to unwrap the Promise in the wrapper's return value to resolve this issue, but encountered type errors:
function wrapper<T,U>(fn: (...args: T[]) => U): (...args: T[]) => Promise<U extends Promise<infer V> ? V : U> {
return (...args: T[]) => doesPromiseyThings(fn);
}
/*
Type '(...args: T[]) => Promise<U>' is not assignable to type '(...args: T[]) => Promise<U extends Promise<infer V> ? V : U>'.
Type 'Promise<U>' is not assignable to type 'Promise<U extends Promise<infer V> ? V : U>'.
Type 'U' is not assignable to type 'U extends Promise<infer V> ? V : U'.(2322)
*/