neverthrow icon indicating copy to clipboard operation
neverthrow copied to clipboard

[Question] Result <X,never> handling

Open mheinzerling opened this issue 8 months ago • 0 comments

I'm new to this topic and started experimenting. I realized that I'm missing some helper methods for cases of Result<X,never>. Implementing my own result for educational purpose resulted in the code below:


export class Result<OK, ERR> {
  static ok<OK>(ok: OK): Result<OK, never> {
    return new Result<OK, never>(ok, NEVER);
  }

  static err<ERR>(err: ERR): Result<never, ERR> {
    return new Result<never, ERR>(NEVER, err);
  }

  private constructor(
    private readonly ok: OK | typeof NEVER,
    private readonly err: ERR | typeof NEVER) {
  }

  private isOk(): this is Result<OK, never> {
    return this.ok !== NEVER;
  }

  private isErr(): this is Result<never, ERR> {
    return this.err !== NEVER;
  }

  unwrap(this: Result<OK, never>): OK {
    return this.match(o => o);
  }

  unwrapError(this: Result<never, ERR>): ERR {
    if (this.isOk()) throw new Error('Should not happen');
    return this.err as ERR;
  }

  map<T>(fn: (value: OK) => T): Result<T, ERR> {
    return this.isOk() ? Result.ok(fn(this.ok as OK)) : Result.err(this.err as ERR);
  }

  mapError<T>(fn: (error: ERR) => T): Result<OK, T> {
    return this.isErr() ? Result.err(fn(this.err as ERR)) : Result.ok(this.ok as OK);
  }

  match<O>(this: Result<OK, never>, okCallback: (value: OK) => O): O;
  match<O, E>(okCallback: (value: OK) => O, errCallback: (error: ERR) => E): O | E;
  match<O, E>(okCallback: (value: OK) => O, errCallback?: (error: ERR) => E): O | E {
    if (this.isOk()) return okCallback(this.ok as OK);
    if (errCallback) return errCallback(this.err as ERR);
    throw new Error('Should not happen');
  }
}

How is this unwrap(this: Result<OK, never>): OK or match<O>(this: Result<OK, never>, okCallback: (value: OK) => O): O; correctly handled in neverthrow?

mheinzerling avatar Apr 15 '25 13:04 mheinzerling