badrap / result

A TypeScript result type taking cues from Rust's Result and Haskell's Either types
MIT License
292 stars 6 forks source link

Want to use if/else condition #19

Closed fukaoi closed 2 years ago

fukaoi commented 2 years ago

Thanks for the great library. I would like to use the following


  const res = Result.ok('test');  

  if (res.isOk) {
      console.log(res.value);
  } else {
      console.log(res.error);  // compile error
  }

However, I get a compile error ”console.log(res.error);”, and I'm thinking the typescript compiler is not able to infer types.

It returns the following error

[tsserver 2339] [E] Property 'error' does not exist on type 'Result<string,Error>'. Property 'error' does not exist on type 'Ok<string, Error>'.

To pass through the compiler, Explicit type definitions are necessary, but not elegant.


    const res = Result.ok('test');
    if (res.isOk) {
      console.log(res.value);
    } else {
      console.log((res as Result.Err<string, Error>).error);
    }

Is there a simpler way to define it, or a way to customize the library itself?

jviide commented 2 years ago

Thanks for the report! It's interesting that we do use this same pattern quite extensively in our internal code. However, we have compilerOptions.strict enabled in our tsconfig.json files, and disabling it causes TypeScript start giving out the errors you describe.

That makes me think that this behavior is likely related to the TypeScript issue https://github.com/microsoft/TypeScript/issues/10564. As such there's not much we can do on the library level, so I recommend you try one of the following approaches:

  1. Enable compilerOptions.strictNullChecks (or compilerOptions.strict) in your tsconfig.json if it's feasible in your environment.

  2. If you can't modify the TypeScript configuration, then use unwrap:

    const res = Result.ok("test");
    
    res.unwrap(
      (value) => {
        console.log(value);
      },
      (err) => {
        console.log(err);
      }
    );
  3. Or instead of unwrap, try isErr if you so prefer:

    const res = Result.ok("test");
    
    if (res.isOk) {
      console.log(res.value);
    } else if (res.isErr) {
      console.log(res.error);
    }
fukaoi commented 2 years ago

@jviide

Thanks for the reply! I also appreciate your detailed explanation, it sounds like a typescript issue.

I will try to deal with this res.unwrap((value) => {}, (err) => {}). I think it is a very cool solution with the same format as match in functional languages.

I hopefully this gets fixed in Typescript :+1: