Skip to content

Instantly share code, notes, and snippets.

@greyblake
Created December 22, 2021 20:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save greyblake/2c81f24645309921cf65362b5726420a to your computer and use it in GitHub Desktop.
Save greyblake/2c81f24645309921cf65362b5726420a to your computer and use it in GitHub Desktop.
Result in TypeScript with normal pattern matching
type ResultInner<T, E> =
| { type: 'OK', value: T }
| { type: 'ERROR', error: E };
interface MatchHandlers<T, E, R> {
ok: (value: T) => R,
err: (error: E) => R,
}
class Result<T, E> {
inner: ResultInner<T, E>;
constructor(inner: ResultInner<T, E>) {
this.inner = inner;
}
public static newOk<T, E>(value: T): Result<T, E> {
const inner: ResultInner<T, E> = { type: 'OK', value, };
return new Result<T, E>(inner);
}
public static newErr<T, E>(error: E): Result<T, E> {
const inner: ResultInner<T, E> = { type: 'ERROR', error, };
return new Result<T, E>(inner);
}
match<R>(handlers: MatchHandlers<T, E, R>): R {
switch (this.inner.type) {
case 'OK': {
return handlers.ok(this.inner.value);
}
case 'ERROR': {
return handlers.err(this.inner.error);
}
default:
throw new Error("Result.match() is supposed to be exhaustive");
}
}
mapOk<T2>(transform: (val: T) => T2): Result<T2, E> {
return this.match({
ok: (val) => Result.newOk(transform(val)),
err: (e) => Result.newErr(e),
});
}
isOk(): boolean {
return this.match({
ok: (_) => true,
err: (_) => false,
});
}
isErr(): boolean {
return !this.isOk();
}
err(): E | null {
return this.match({
ok: (_) => null,
err: (e) => e,
});
}
ok(): T | null {
return this.match({
ok: (val) => val,
err: (_) => null,
});
}
unwrap(): T {
return this.match({
ok: (val) => val,
err: (e) => {
throw new Error(`Cannot unwrap Result with an error: ${e}`);
},
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment