/** [[include:doc/result.md]] */ /** (keep typedoc from getting confused by the import) */ import * as Maybe from './maybe'; import Unit from './unit'; import { _Brand, curry1, isVoid } from './utils'; // So that it doesn't appear unused but can be exported. _Brand; // tslint:disable-line:no-unused-expression /** Discriminant for `Ok` and `Err` variants of `Result` type. You can use the discriminant via the `variant` property of `Result` instances if you need to match explicitly on it. */ export var Variant; (function (Variant) { Variant["Ok"] = "Ok"; Variant["Err"] = "Err"; })(Variant || (Variant = {})); /** An `Ok` instance is the *successful* variant instance of the [`Result`](../modules/_result_.html#result) type, representing a successful outcome from an operation which may fail. For a full discussion, see [the module docs](../modules/_result_.html). @typeparam T The type wrapped in this `Ok` variant of `Result`. @typeparam E The type which would be wrapped in an `Err` variant of `Result`. */ export class Ok { /** Create an instance of `Result.Ok` with `new`. Note: While you *may* create the `Result` type via normal JavaScript class construction, it is not recommended for the functional style for which the library is intended. Instead, use [`Result.ok`]. [`Result.ok`]: ../modules/_result_.html#ok ```ts // Avoid: const aString = new Result.Ok('characters'); // Prefer: const aString = Result.ok('characters); ``` Note that you may explicitly pass `Unit` to the `Ok` constructor to create a `Result`. However, you may *not* call the `Ok` constructor with `null` or `undefined` to get that result (the type system won't allow you to construct it that way). Instead, for convenience, you can simply call `Result.ok()`, which will construct the type correctly. @param value The value to wrap in a `Result.Ok`. Note: `null` and `undefined` are allowed by the type signature so that the constructor may `throw` on those rather than constructing a type like `Result`. @throws If you pass `null`. */ constructor(value) { /** `Ok` is always [`Variant.Ok`](../enums/_result_.variant#ok). */ this.variant = Variant.Ok; if (isVoid(value)) { throw new Error('Tried to construct `Ok` with `null` or `undefined`. Maybe you want `Maybe.Nothing`?'); } this.value = value; } /** Unwrap the contained value. A convenience method for functional idioms. A common scenario where you might want to use this is in a pipeline of functions: ```ts import Result, { Ok } from 'true-myth/result'; function getLengths(results: Array>): Array { return results .filter(Result.isOk) .map(Ok.unwrap) .map(s => s.length); } ``` */ static unwrap(theOk) { return theOk.value; } /** Method variant for [`Result.isOk`](../modules/_result_.html#isok) */ isOk() { return true; } /** Method variant for [`Result.isErr`](../modules/_result_.html#iserr) */ isErr() { return false; } /** Method variant for [`Result.map`](../modules/_result_.html#map) */ map(mapFn) { return map(mapFn, this); } /** Method variant for [`Result.mapOr`](../modules/_result_.html#mapor) */ mapOr(orU, mapFn) { return mapOr(orU, mapFn, this); } /** Method variant for [`Result.mapOrElse`](../modules/_result_.html#maporelse) */ mapOrElse(orElseFn, mapFn) { return mapOrElse(orElseFn, mapFn, this); } /** Method variant for [`Result.match`](../modules/_result_.html#match) */ match(matcher) { return match(matcher, this); } /** Method variant for [`Result.mapErr`](../modules/_result_.html#maperr) */ mapErr(mapErrFn) { return mapErr(mapErrFn, this); } /** Method variant for [`Result.or`](../modules/_result_.html#or) */ or(orResult) { return or(orResult, this); } /** Method variant for [`Result.orElse`](../modules/_result_.html#orelse) */ orElse(orElseFn) { return orElse(orElseFn, this); } /** Method variant for [`Result.and`](../modules/_result_.html#and) */ and(mAnd) { return and(mAnd, this); } /** Method variant for [`Result.andThen`](../modules/_result_.html#andthen) */ andThen(andThenFn) { return andThen(andThenFn, this); } /** Method variant for [`Result.chain`](../modules/_result_.html#chain) */ chain(chainFn) { return chain(chainFn, this); } /** Method variant for [`Result.flatMap`](../modules/_result_.html#flatmap) */ flatMap(flatMapFn) { return flatMap(flatMapFn, this); } /** Method variant for [`Result.unwrap`](../modules/_result_.html#unwrap) */ unsafelyUnwrap() { return this.value; } /** Method variant for [`Result.unwrapErr`](../modules/_result_.html#unwraperr) */ unsafelyUnwrapErr() { throw new Error('Tried to `unsafelyUnwrapErr` an `Ok`'); } /** Method variant for [`Result.unwrapOr`](../modules/_result_.html#unwrapor) */ unwrapOr(defaultValue) { return unwrapOr(defaultValue, this); } /** Method variant for [`Result.unwrapOrElse`](../modules/_result_.html#unwrapOrElse) */ unwrapOrElse(elseFn) { return unwrapOrElse(elseFn, this); } /** Method variant for [`Result.toMaybe`](../modules/_result_.html#tomaybe) */ toMaybe() { return toMaybe(this); } /** Method variant for [`Result.toString`](../modules/_result_.html#tostring) */ toString() { return toString(this); } /** Method variant for [`Result.toJSON`](../modules/_result_.html#toJSON) */ toJSON() { return toJSON(this); } /** Method variant for [`Result.equals`](../modules/_result_.html#equals) */ equals(comparison) { return equals(comparison, this); } /** Method variant for [`Result.ap`](../modules/_result_.html#ap) */ ap(r) { return ap(this, r); } } /** An `Err` instance is the *failure* variant instance of the [`Result`](../modules/_result_.html#result) type, representing a failure outcome from an operation which may fail. For a full discussion, see [the module docs](../modules/_result_.html). @typeparam T The type which would be wrapped in an `Ok` variant of `Result`. @typeparam E The type wrapped in this `Err` variant of `Result`. */ export class Err { /** Create an instance of `Result.Err` with `new`. Note: While you *may* create the `Result` type via normal JavaScript class construction, it is not recommended for the functional style for which the library is intended. Instead, use [`Result.err`]. [`Result.err`]: ../modules/_result_.html#err ```ts // Avoid: const anErr = new Result.Err('alas, failure'); // Prefer: const anErr = Result.err('alas, failure'); ``` Note that you may explicitly pass `Unit` to the `Err` constructor to create a `Result`. However, you may *not* call the `Err` constructor with `null` or `undefined` to get that result (the type system won't allow you to construct it that way). Instead, for convenience, you can simply call `Result.err()`, which will construct the type correctly. @param error The value to wrap in a `Result.Err`. `Note: null` and `undefined` are allowed by the type signature so that the constructor may `throw` on those rather than constructing a type like `Result`. @throws If you pass `null` or `undefined`. */ constructor(error) { /** `Err` is always [`Variant.Err`](../enums/_result_.variant#err). */ this.variant = Variant.Err; if (isVoid(error)) { throw new Error('Tried to construct `Err` with `null` or `undefined`. Maybe you want `Maybe.Nothing`?'); } this.error = error; } /** Unwrap the contained error . A convenience method for functional idioms. A common scenario where you might want to use this is in a pipeline of functions: ```ts import Result, { Ok } from 'true-myth/result'; function getMessages(results: Array>): Array { return maybeStrings .filter(Result.isErr) .map(Err.unwrapErr) .map(e => e.message); } ``` */ static unwrapErr(theErr) { return theErr.error; } /** Method variant for [`Result.isOk`](../modules/_result_.html#isok) */ isOk() { return false; } /** Method variant for [`Result.isErr`](../modules/_result_.html#iserr) */ isErr() { return true; } /** Method variant for [`Result.map`](../modules/_result_.html#map) */ map(mapFn) { return map(mapFn, this); } /** Method variant for [`Result.mapOr`](../modules/_result_.html#mapor) */ mapOr(orU, mapFn) { return mapOr(orU, mapFn, this); } /** Method variant for [`Result.mapOrElse`](../modules/_result_.html#maporelse) */ mapOrElse(orElseFn, mapFn) { return mapOrElse(orElseFn, mapFn, this); } /** Method variant for [`Result.match`](../modules/_result_.html#match) */ match(matchObj) { return match(matchObj, this); } /** Method variant for [`Result.mapErr`](../modules/_result_.html#maperr) */ mapErr(mapErrFn) { return mapErr(mapErrFn, this); } /** Method variant for [`Result.or`](../modules/_result_.html#or) */ or(orResult) { return or(orResult, this); } /** Method variant for [`Result.orElse`](../modules/_result_.html#orelse) */ orElse(orElseFn) { return orElse(orElseFn, this); } /** Method variant for [`Result.and`](../modules/_result_.html#and) */ and(mAnd) { return and(mAnd, this); } /** Method variant for [`Result.andThen`](../modules/_result_.html#andthen) */ andThen(andThenFn) { return andThen(andThenFn, this); } /** Method variant for [`Result.chain`](../modules/_result_.html#chain) */ chain(chainFn) { return this.andThen(chainFn); } /** Method variant for [`Result.flatMap`](../modules/_result_.html#flatmap) */ flatMap(flatMapFn) { return this.andThen(flatMapFn); } /** Method variant for [`Result.unsafelyUnwrap`](../modules/_result_.html#unsafelyunwrap) */ unsafelyUnwrap() { throw new Error('Tried to `unsafelyUnwrap an Err`'); } /** Method variant for [`Result.unsafelyUnwrapErr`](../modules/_result_.html#unsafelyunwraperr) */ unsafelyUnwrapErr() { return this.error; } /** Method variant for [`Result.unwrapOr`](../modules/_result_.html#unwrapor) */ unwrapOr(defaultValue) { return unwrapOr(defaultValue, this); } /** Method variant for [`Result.unwrapOrElse`](../modules/_result_.html#unwraporelse) */ unwrapOrElse(elseFn) { return unwrapOrElse(elseFn, this); } /** Method variant for [`Result.toMaybe`](../modules/_result_.html#tomaybe) */ toMaybe() { return toMaybe(this); } /** Method variant for [`Result.toString`](../modules/_result_.html#tostring) */ toString() { return toString(this); } /** Method variant for [`Result.toJSON`](../modules/_result_.html#toJSON) */ toJSON() { return toJSON(this); } /** Method variant for [`Result.equals`](../modules/_result_.html#equals) */ equals(comparison) { return equals(comparison, this); } /** Method variant for [`Result.ap`](../modules/_result_.html#ap) */ ap(r) { return ap(this, r); } } /** Is this `Result` an `Ok` instance? In TypeScript, narrows the type from `Result` to `Ok`. */ export function isOk(result) { return result.variant === Variant.Ok; } /** Is this `Result` an `Err` instance? In TypeScript, narrows the type from `Result` to `Err`. */ export function isErr(result) { return result.variant === Variant.Err; } export function ok(value) { return value === undefined ? new Ok(Unit) : new Ok(value); } /** `Result.of` is an alias for `Result.ok`. */ export const of = ok; export function err(error) { return isVoid(error) ? new Err(Unit) : new Err(error); } export function tryOr(error, callback) { const op = (cb) => { try { return Result.ok(cb()); } catch (_a) { return Result.err(error); } }; return curry1(op, callback); } export function tryOrElse(onError, callback) { const op = (cb) => { try { return Result.ok(cb()); } catch (e) { return Result.err(onError(e)); } }; return curry1(op, callback); } export function map(mapFn, result) { const op = (r) => (isOk(r) ? ok(mapFn(r.value)) : r); return curry1(op, result); } export function mapOr(orU, mapFn, result) { function fullOp(fn, r) { return isOk(r) ? fn(r.value) : orU; } function partialOp(fn, curriedResult) { return curriedResult !== undefined ? fullOp(fn, curriedResult) : (extraCurriedResult) => fullOp(fn, extraCurriedResult); } return mapFn === undefined ? partialOp : result === undefined ? partialOp(mapFn) : partialOp(mapFn, result); } export function mapOrElse(orElseFn, mapFn, result) { function fullOp(fn, r) { return isOk(r) ? fn(r.value) : orElseFn(r.error); } function partialOp(fn, curriedResult) { return curriedResult !== undefined ? fullOp(fn, curriedResult) : (extraCurriedResult) => fullOp(fn, extraCurriedResult); } return mapFn === undefined ? partialOp : result === undefined ? partialOp(mapFn) : partialOp(mapFn, result); } export function mapErr(mapErrFn, result) { const op = (r) => (isOk(r) ? r : err(mapErrFn(r.error))); return curry1(op, result); } export function and(andResult, result) { const op = (r) => (isOk(r) ? andResult : r); return curry1(op, result); } export function andThen(thenFn, result) { const op = (r) => (isOk(r) ? thenFn(r.value) : r); return curry1(op, result); } /** Alias for [`andThen`](#andthen). */ export const chain = andThen; /** Alias for [`andThen`](#andthen). */ export const flatMap = andThen; export function or(defaultResult, result) { const op = (r) => (isOk(r) ? r : defaultResult); return curry1(op, result); } export function orElse(elseFn, result) { const op = (r) => (isOk(r) ? r : elseFn(r.unsafelyUnwrapErr())); return curry1(op, result); } /** Get the value out of the `Result`. Returns the content of an `Ok`, but **throws if the `Result` is `Err`.** Prefer to use [`unwrapOr`](#unwrapor) or [`unwrapOrElse`](#unwraporelse). @throws If the `Result` instance is `Nothing`. */ export function unsafelyUnwrap(result) { return result.unsafelyUnwrap(); } /** Alias for [`unsafelyUnwrap`](#unsafelyunwrap) */ export const unsafelyGet = unsafelyUnwrap; /** Alias for [`unsafelyUnwrap`](#unsafelyunwrap) */ export const unsafeGet = unsafelyUnwrap; /** Get the error value out of the [`Result`](#result). Returns the content of an `Err`, but **throws if the `Result` is `Ok`**. Prefer to use [`unwrapOrElse`](#unwraporelse). @param result @throws Error If the `Result` instance is `Nothing`. */ export function unsafelyUnwrapErr(result) { return result.unsafelyUnwrapErr(); } /** Alias for [`unsafelyUnwrapErr`](#unsafelyunwraperr) */ export const unsafelyGetErr = unsafelyUnwrapErr; export function unwrapOr(defaultValue, result) { const op = (r) => (isOk(r) ? r.value : defaultValue); return curry1(op, result); } /** Alias for [`unwrapOr`](#unwrapor) */ export const getOr = unwrapOr; export function unwrapOrElse(orElseFn, result) { const op = (r) => (isOk(r) ? r.value : orElseFn(r.error)); return curry1(op, result); } /** Alias for [`unwrapOrElse`](#unwraporelse) */ export const getOrElse = unwrapOrElse; /** Convert a [`Result`](#result) to a [`Maybe`](../modules/_maybe_.html#maybe). The converted type will be [`Just`] if the `Result` is [`Ok`] or [`Nothing`] if the `Result` is [`Err`]; the wrapped error value will be discarded. [`Just`]: ../classes/_maybe_.just.html [`Nothing`]: ../classes/_maybe_.nothing.html [`Ok`]: ../classes/_result_.ok.html [`Err`]: ../classes/_result_.err.html @param result The `Result` to convert to a `Maybe` @returns `Just` the value in `result` if it is `Ok`; otherwise `Nothing` */ export function toMaybe(result) { return isOk(result) ? Maybe.just(result.value) : Maybe.nothing(); } export function fromMaybe(errValue, maybe) { const op = (m) => Maybe.isJust(m) ? ok(Maybe.unsafelyUnwrap(m)) : err(errValue); return curry1(op, maybe); } /** Create a `String` representation of a `result` instance. An `Ok` instance will be printed as `Ok()`, and an `Err` instance will be printed as `Err()`, where the representation of the value or error is simply the value or error's own `toString` representation. For example: call | output --------------------------------- | ---------------------- `toString(ok(42))` | `Ok(42)` `toString(ok([1, 2, 3]))` | `Ok(1,2,3)` `toString(ok({ an: 'object' }))` | `Ok([object Object])`n `toString(err(42))` | `Err(42)` `toString(err([1, 2, 3]))` | `Err(1,2,3)` `toString(err({ an: 'object' }))` | `Err([object Object])` @typeparam T The type of the wrapped value; its own `.toString` will be used to print the interior contents of the `Just` variant. @param maybe The value to convert to a string. @returns The string representation of the `Maybe`. */ export const toString = (result) => { const body = (isOk(result) ? result.value : result.error).toString(); return `${result.variant.toString()}(${body})`; }; /** * Create an `Object` representation of a `Result` instance. * * Useful for serialization. `JSON.stringify()` uses it. * * @param result The value to convert to JSON * @returns The JSON representation of the `Result` */ export const toJSON = (result) => { return result.isOk() ? { variant: result.variant, value: result.value } : { variant: result.variant, error: result.error }; }; export function match(matcher, result) { const op = (r) => mapOrElse(matcher.Err, matcher.Ok, r); return curry1(op, result); } /** Alias for [`match`](#match) */ export const cata = match; export function equals(resultB, resultA) { return resultA !== undefined ? resultA.match({ Err: () => isErr(resultB), Ok: a => isOk(resultB) && resultB.unsafelyUnwrap() === a, }) : (curriedResultA) => curriedResultA.match({ Err: () => isErr(resultB), Ok: a => isOk(resultB) && resultB.unsafelyUnwrap() === a, }); } export function ap(resultFn, result) { const op = (r) => r.match({ Ok: val => resultFn.map(fn => fn(val)), Err: e => Result.err(e), }); return curry1(op, result); } /** Determine whether an item is an instance of `Just` or `Nothing`. @param item The item to check. */ export function isInstance(item) { return item instanceof Ok || item instanceof Err; } export const Result = { Variant, Ok, Err, isOk, isErr, ok, err, tryOr, tryOrElse, map, mapOr, mapOrElse, mapErr, and, andThen, chain, flatMap, or, orElse, unsafelyUnwrap, unsafelyGet, unsafeGet, unsafelyUnwrapErr, unsafelyGetErr, unwrapOr, getOr, unwrapOrElse, getOrElse, toMaybe, fromMaybe, toString, toJSON, match, cata, equals, ap, isInstance, }; export default Result; //# sourceMappingURL=result.js.map