UNPKG

resulty

Version:

A disjunction implementation in TypeScript.

239 lines (232 loc) 6.47 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); // src/index.ts var Result = class _Result { constructor(state) { this.state = state; } /** * Construct a successful result * @param value a value to wrap in Ok * @returns a new Result with the value wrapped in Ok */ static ok(value) { return new _Result({ kind: "ok", value }); } /** * Construct a failed result * @param error a value to wrap in Err * @returns a new Result with the value wrapped in Err */ static err(error) { return new _Result({ kind: "err", error }); } /** * Returns true if the result is a success */ isOk() { return this.state.kind === "ok"; } /** * Returns true if the result is a failure */ isErr() { return this.state.kind === "err"; } /** * Returns the value from a successful result. For an error, returns the * result of evaluating the fn */ getOrElse(fn) { switch (this.state.kind) { case "ok": return this.state.value; case "err": return fn(); } } /** * Returns the value from a successful result. Returns the defaultValue if * the result was a failure. */ getOrElseValue(defaultValue) { switch (this.state.kind) { case "ok": return this.state.value; case "err": return defaultValue; } } /** * Returns a new result after applying fn to the value stored in a successful * result. If the result was a failure, then the Err result is simply * returned. */ map(fn) { switch (this.state.kind) { case "ok": return _Result.ok(fn(this.state.value)); case "err": return _Result.err(this.state.error); } } /** * An alias for `map` */ and(fn) { return this.map(fn); } /** * Returns a new result after applying fn to the error value. successful * results are returned unchanged. */ mapError(fn) { switch (this.state.kind) { case "ok": return _Result.ok(this.state.value); case "err": return _Result.err(fn(this.state.error)); } } /** * Chains together two computations that return results. If the result is a * success, then the second computation is run. Otherwise, the Err is * returned. */ andThen(fn) { switch (this.state.kind) { case "ok": return fn(this.state.value); case "err": return _Result.err(this.state.error); } } /** * Runs an alternative computation in the case that the first computation * resulted in an Err. */ orElse(fn) { switch (this.state.kind) { case "ok": return _Result.ok(this.state.value); case "err": return fn(this.state.error); } } /** * Folds over types; a switch/case for success or failure. */ cata(matcher) { switch (this.state.kind) { case "ok": return matcher.Ok(this.state.value); case "err": return matcher.Err(this.state.error); } } /** * Encapsulates a common pattern of needing to build up an Object from * a series of Result values. This is often solved by nesting `andThen` calls * and then completing the chain with a call to `ok`. * * This feature was inspired (and the code lifted from) this article: * https://medium.com/@dhruvrajvanshi/simulating-haskells-do-notation-in-typescript-e48a9501751c * * Wrapped values are converted to an Object using the Object constructor * before assigning. Primitives won't fail at runtime, but results may * be unexpected. */ assign(k, other) { const state = this.state; switch (state.kind) { case "ok": { const result = typeof other === "function" ? other(state.value) : other; return result.map((b) => __spreadProps(__spreadValues({}, Object(state.value)), { [k.toString()]: b })); } case "err": return _Result.err(state.error); } } /** * Inject a side-effectual operation into a chain of Result computations. * * The primary use case for `do` is to perform logging in the middle of a flow * of Results. * * The side effect only runs when there isn't an error (Ok). * * The value will (should) remain unchanged during the `do` operation. * * ok({}) * .assign('foo', ok(42)) * .assign('bar', ok('hello')) * .do(scope => console.log('Scope: ', JSON.stringify(scope))) * .map(doSomethingElse) * */ do(fn) { switch (this.state.kind) { case "ok": fn(this.state.value); return this; case "err": return this; } } /** * Inject a side-effectual operation into a chain of Result computations. * * The side effect only runs when there is an error (Err). * * The value will remain unchanged during the `elseDo` operation. * * ok({}) * .assign('foo', ok(42)) * .assign('bar', err('hello')) * .elseDo(scope => console.log('Scope: ', JSON.stringify(scope))) * .map(doSomethingElse) * */ elseDo(fn) { switch (this.state.kind) { case "ok": return this; case "err": fn(this.state.error); return this; } } }; function ok(value) { return Result.ok(value); } function err(error) { return Result.err(error); } function isOk(result) { return result.isOk(); } function isErr(result) { return result.isErr(); } exports.Result = Result; exports.err = err; exports.isErr = isErr; exports.isOk = isOk; exports.ok = ok; //# sourceMappingURL=index.cjs.map