Issue
I have the following function that allows me to handle async errors similar to Go.
type AsyncResults<ErrorType, DataType> = Promise<
readonly [undefined, DataType] | readonly [ErrorType, undefined]
>;
const asyncHandler = <ErrorType, DataType>(
asyncFunc: Promise<DataType>,
): AsyncResults<ErrorType, DataType> => {
return asyncFunc
.then((data: DataType) => [undefined, data] as const)
.catch((error: ErrorType) =>
Promise.resolve([error, undefined] as const),
);
};
When I call it, I usually get error type to be 'unknown', which is ok, but my result type is always whatever is inferred union undefined
const [err, verifiedUser] = await asyncHandler(
getPasswordVerifiedUser(db, {
email,
password,
}),
);
if (err) throw err
const user: VerifiedUser = {
firstName: verifiedUser.firstName (TS complains that object may be undefined)
}
So verifiedUser above has inferred type 'Document | undefined'. Is there a way for TypeScript to know that if err is undefined then verifiedUser cannot be undefined (and vice versa)? I want that if I handle the err by throwing or returning, TS recognizes that verifiedUser can no longer be undefined.
Solution
What you are trying to do is impossible. TypeScript does not make any difference between a resolution and a rejection. This is how reject and resolve are being typed:
reject<T = never>(reason?: any): Promise<T>;
resolve<T>(value: T | PromiseLike<T>): Promise<T>;
They both return Promise<T> so there is no possible way to narrow down a Promise's return type based on the control-flow.
More information about this here: https://github.com/Microsoft/TypeScript/issues/7588#issuecomment-199079907
Edit:
If you want to narrow the tuple type union, just don't destructure it:
// Considering ErrorType is number and DataType is { firstName: string }
const result = await asyncHandler<number, { firstName: string }>(
getPasswordVerifiedUser<{ firstName: string }>(),
);
if (result[0] !== undefined) throw result[0]
const user = {
firstName: result[1].firstName // works
}
It's the only solution that I found and it seems to be confirmed here: Control flow not type-narrowing with union tuple?
Answered By - Guerric P
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.