Skip to content
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

Mentioned safeTry Error Inference Limitations in Docs #604

Open
lucaschultz opened this issue Oct 27, 2024 · 1 comment
Open

Mentioned safeTry Error Inference Limitations in Docs #604

lucaschultz opened this issue Oct 27, 2024 · 1 comment

Comments

@lucaschultz
Copy link

In #603, @pierback mentioned that only the first yield is considered in the safeTry type inference due to a TypeScript limitation (see microsoft/TypeScript#57625). This is a significant drawback of using safeTry and should be noted in the documentation, as it can easily lead to bugs due to incomplete error handling. I'll have to check my codebases now and see wether this is an issue in my code 😌

Perhaps neverthrow could include an example like this:

class MyError1 extends Error {}
class MyError2 extends Error {}

declare function mayFail1(): Result<number, MyError1>
declare function mayFail2(): Result<number, MyError2>

// Return type is Result<number | null, MyError1 | MyError2>
function myFunc() { 
  return safeTry<number | null, MyError1 | MyError2>(function* () {
    const value1 = yield* mayFail1()
    const value2 = yield* mayFail2()

    const result = value1 + value2

    if (result < 0) {
      return ok(null)
    }

    return ok(result)
  })
}

// Inferred return type is Result<number | null, MyError1>
function myInferredFunc() { 
  return safeTry(function* () {
    const value1 = yield* mayFail1()
    const value2 = yield* mayFail2()

    const result = value1 + value2

    if (result < 0) {
      return ok(null)
    }

    return ok(result)
  })
}

Including this in the safeTry documentation would illustrate both the issue and the expected inference of ok values. The documentation should also emphasize that when using safeTry, developers must always specify all potential errors as generics.

@janglad
Copy link

janglad commented Oct 30, 2024

FYI, you can use a tag (or really any property that differentiates the 2 types) to prevent this. I would suggest instead updating the documentation to recommend this approach.

import { ok, Result, safeTry } from "neverthrow";
class MyError1 extends Error {
  readonly _tag = "MyError1";
}
class MyError2 extends Error {
  readonly _tag = "MyError2";
}

declare function mayFail1(): Result<number, MyError1>;
declare function mayFail2(): Result<number, MyError2>;

const test = safeTry(function* () {
  yield* mayFail1();
  yield* mayFail2();
  return ok("Hello");
});

// const test: Result<string, MyError1 | MyError2>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants