-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
safeTry
with ResultAsync
doesn't infer combined error types from multiple yields
#603
Comments
It doesn't work with multiple |
This is probably a regression introduced by v8.1 right? It seems to be working with 8.0 and using |
Does not seem to work in previous versions either. Still infers/picks the error from the first function mayFail1Sync(success: boolean): Result<number, MyError1> {
if (success) {
return ok(20)
}
return err(new MyError1('Error from mySyncFail1'))
}
function mayFail2Sync(success: boolean): Result<number, MyError2> {
if (success) {
return ok(20)
}
return err(new MyError2('Error from mySyncFail2'))
}
const main = () =>
safeTry(function* () {
const val1Result = yield* mayFail1Sync(true);
const val2Result = yield* mayFail2Sync(false);
return ok(val1Result + val2Result);
}).mapErr((e) => `Aborted by an error: ${e}`);
|
After further investigation, I found that this is sadly a limitation of TypeScript's generator implementation: microsoft/TypeScript#57625 |
Made a similar comment in #604 but leaving it here too for visibility. You can use a readonly property (or anything that differentiates the 2 types) to prevent this import { ok, err, ResultAsync, Result, safeTry } from 'neverthrow';
class MyError1 extends Error {
readonly name = 'MyError1';
constructor(message: string) {
super(message);
}
}
class MyError2 extends Error {
readonly name = 'MyError2';
constructor(message: string) {
super(message);
}
}
// Simulate an async function that may succeed or fail
function mayFail1(success: boolean): ResultAsync<number, MyError1> {
return new ResultAsync(
new Promise<Result<number, MyError1>>((resolve) => {
setTimeout(() => {
if (success) {
resolve(ok(20));
} else {
resolve(err(new MyError1('Error from mayFail1')));
}
}, 100);
}),
);
}
// Simulate another async function that may succeed or fail
function mayFail2(success: boolean): ResultAsync<number, MyError2> {
return new ResultAsync(
new Promise<Result<number, MyError2>>((resolve) => {
setTimeout(() => {
if (success) {
resolve(ok(20));
} else {
resolve(err(new MyError2('Error from mayFail2')));
}
}, 100);
}),
);
}
const main = () =>
safeTry(async function* () {
const val1Result = yield* mayFail1(true);
const val2Result = yield* mayFail2(false);
return ok(val1Result + val2Result);
}).mapErr((e) => `Aborted by an error: ${e}`);
// (parameter) e: MyError1 | MyError2 |
Hi, I'm using
safeTry
with multipleResultAsync
instances, and I think it would be beneficial if TypeScript could infer the union of all possible error types from the yielded values.Example Code:
Currently, TypeScript only infers the error type from the first yielded
ResultAsync
(mayFail1
), which meanse
inmapErr
is inferred asMyError1
. As a result,MyError2
is not recognized as a possible error type.Ideally, TypeScript should infer the error type for
mapErr
asMyError1 | MyError2
to account for all possible errors that could arise from the yieldedResultAsync
instances.Is there a way to enhance
safeTry
to infer all possible error types without requiring explicit annotations?The text was updated successfully, but these errors were encountered: