In the code snippet below, I am attempting to specify the type of the resolve
callback.
Initially: Generic Approach
export interface PromiseHandler<T> {
resolve: (result: T) => void // <----- My query is about this line
reject: (error: any) => void
promise: Promise<T>
}
export function createPromiseHandler<T = any>(): PromiseHandler<T> {
let resolve!: any;
let reject!: (error: any) => void;
const promise = new Promise<T>((onResolve, onReject) => {
resolve = onResolve;
reject = onReject;
});
return { promise, resolve, reject };
}
const handler1 = createPromiseHandler<boolean>();
handler1.resolve(true); // This works fine
const handler2 = createPromiseHandler<void>();
handler2.resolve(); // This also works without issues
While it functions as desired, there's a type mismatch:
const handler3 = createPromiseHandler<void>();
const voidResolve: () => void = handler3.resolve // Error: Type '(result: void) => void' is not assignable to type '() => void'.
Second Attempt: Introducing Conditional Types
export interface PromiseHandler<T> {
resolve: T extends void ? () => void : (result: T) => void
reject: (error: any) => void
promise: Promise<T>
}
const handler4 = createPromiseHandler<void>();
const voidResolve2: () => void = handler4.resolve // This now works correctly
The previous issue has been resolved. However, a new problem arises with the primary scenario:
const handler5 = createPromiseHandler<boolean>();
handler5.resolve(true); // Error: Argument of type 'true' is not assignable to parameter of type 'false & true'.
When using conditional types, somehow a union (boolean
as false | true
) gets converted to an intersection (false & true
)! It's puzzling.