UNPKG

@jumpaku/async-result

Version:

A typescript library that provides Result, Option, and AsyncResult.

202 lines 6.21 kB
import { BaseError } from "make-error-cause"; import { AsyncResult } from "./AsyncResult"; export class ResultError extends BaseError { constructor(error) { super(error instanceof Error ? error.message : "", error instanceof Error ? error : undefined); this.name = "ResultError"; this.detail = error; } } export const Result = { success(value) { return new Success(value); }, failure(error) { return new Failure(error); }, try: (tryFun, catchFun) => { try { return Result.success(tryFun()); } catch (error) { return catchFun == null ? Result.failure(error) : Result.failure(catchFun(error)); } }, isResult(obj) { return obj instanceof AbstractResult; }, }; class AbstractResult { assertsThisIsResult() { if (!this.isSuccess() && !this.isFailure()) throw new Error(); } match(onSuccess, onFailure) { this.assertsThisIsResult(); return this.isSuccess() ? onSuccess(this.value) : onFailure(this.error); } orDefault(value) { return this.isSuccess() ? this.value : value; } orRecover(f) { this.assertsThisIsResult(); return this.isSuccess() ? this.value : f(this.error); } orThrow(f) { this.assertsThisIsResult(); if (this.isFailure()) throw f != null ? f(this.error) : new ResultError(this.error); return this.value; } orNull() { return this.isSuccess() ? this.value : null; } orUndefined() { return this.isSuccess() ? this.value : undefined; } onSuccess(f) { if (this.isSuccess()) f(this.value); this.assertsThisIsResult(); return this; } onFailure(f) { this.assertsThisIsResult(); if (this.isFailure()) f(this.error); return this; } and(other) { return this.isFailure() ? this : other; } or(other) { return this.isSuccess() ? this : other; } map(neverThrowFun) { this.assertsThisIsResult(); return this.isSuccess() ? Result.success(neverThrowFun(this.value)) : this.castValue(); } mapAsync(tryFun, catchFun) { return catchFun == null ? this.match((v) => AsyncResult.try(() => tryFun(v)), (e) => AsyncResult.failure(e)) : this.match((v) => AsyncResult.try(() => tryFun(v), catchFun), (e) => AsyncResult.failure(e)); } tryMap(tryFun, catchFun) { return (catchFun == null ? Result.try(() => this.map(tryFun)) : Result.try(() => this.map(tryFun), catchFun)).flatMap((it) => it); } flatMap(neverThrowFun) { this.assertsThisIsResult(); return this.isSuccess() ? neverThrowFun(this.value) : this.castValue(); } flatMapAsync(tryFun, catchFun) { this.assertsThisIsResult(); if (this.isFailure()) return AsyncResult.of(this.castValue()); try { const result = tryFun(this.value); return Result.isResult(result) ? AsyncResult.of(result) : result; } catch (error) { return catchFun == null ? AsyncResult.failure(error) : AsyncResult.failure(catchFun(error)); } } tryFlatMap(tryFun, catchFun) { return (catchFun == null ? Result.try(() => this.flatMap(tryFun)) : Result.try(() => this.flatMap(tryFun), catchFun)).flatMap((it) => it); } recover(neverThrowFun) { this.assertsThisIsResult(); return this.isFailure() ? Result.success(neverThrowFun(this.error)) : this.castError(); } recoverAsync(tryFun, catchFun) { this.assertsThisIsResult(); const f = async () => { this.assertsThisIsResult(); return this.isSuccess() ? this.value : tryFun(this.error); }; return catchFun == null ? AsyncResult.try(f) : AsyncResult.try(f, catchFun); } tryRecover(tryFun, catchFun) { return (catchFun == null ? Result.try(() => this.recover(tryFun)) : Result.try(() => this.recover(tryFun), catchFun)).flatMap((it) => it); } flatRecover(neverThrowFun) { this.assertsThisIsResult(); return this.isFailure() ? neverThrowFun(this.error) : this.castError(); } flatRecoverAsync(tryFun, catchFun) { this.assertsThisIsResult(); if (this.isSuccess()) return AsyncResult.of(this); try { const result = tryFun(this.error); return Result.isResult(result) ? AsyncResult.of(result) : result; } catch (error) { return catchFun == null ? AsyncResult.failure(error) : AsyncResult.failure(catchFun(error)); } } tryFlatRecover(tryFun, catchFun) { return (catchFun == null ? Result.try(() => this.flatRecover(tryFun)) : Result.try(() => this.flatRecover(tryFun), catchFun)).flatMap((it) => it); } mapError(neverThrowFun) { this.assertsThisIsResult(); return this.isFailure() ? Result.failure(neverThrowFun(this.error)) : this.castError(); } tryMapError(tryFun, catchFun) { return (catchFun == null ? Result.try(() => this.mapError(tryFun)) : Result.try(() => this.mapError(tryFun), catchFun)).flatMap((it) => it); } } export class Success extends AbstractResult { constructor(value) { super(); this.value = value; this.error = undefined; } isSuccess() { return true; } isFailure() { return false; } castError() { return this; } } export class Failure extends AbstractResult { constructor(error) { super(); this.error = error; this.value = undefined; } isSuccess() { return false; } isFailure() { return true; } castValue() { return this; } } //# sourceMappingURL=Result.js.map