UNPKG

lodash-fantasy

Version:

Fantasy Land compatible types built with lodash.

1,083 lines (1,007 loc) 30 kB
"use strict"; // Third Party const include = require("include")(__dirname); const stream = require("lodash/fp"); // Third Party Aliases const concat = stream.concat; const curry = stream.curry; const each = stream.each; const filter = stream.filter; const find = stream.find; const flow = stream.flow; const get = stream.get; const isEqual = stream.isEqual; const isNull = stream.isNull; const isUndefined = stream.isUndefined; const map = stream.map; const negate = stream.negate; const reduce = stream.reduce; // Project const invokeIn = include("src/invokeIn"); /** * The {@link Maybe} type is intended for values that may or may not be null or undefined. It is a disjunction similar * to <code>Either</code>. The key difference of the {@link Maybe} type is the focus on a value or nothing. Much like * <code>Either</code>, {@link Maybe} is right-biased. * @param {*} value - Value to wrap. * @return {Maybe} {@link Maybe} wrapped <code>value</code>. * @example <caption>Via <code>new</code></caption> * * const v1 = new Just(value); * const v2 = new Nothing(); * * @example <caption>Via function</caption> * * const v3 = Just.from(value); * const v4 = Nothing.from(); * * @example <caption>Via Maybe function</caption> * * const getOr = require("lodash/fp/getOr"); * const Maybe = require("lodash-fantasy/data/Maybe"); * * function getValue(path, context) { * return getOr(Maybe.Nothing.from(), path, context); * } * * module.exports = getValue; */ class Maybe { /** * @static * @property {Just} Just - Maybe just. */ static get Just() { return Just; } /** * @static * @property {Nothing} Nothing - Maybe nothing. */ static get Nothing() { return Nothing; } /** * Returns a {@link Maybe} that resolves all of the maybes in the collection into a single Maybe. * @static * @member * @param {Maybe[]} maybes - Collection of maybes. * @return {Maybe} A {@link Maybe} representing all {@link Just} values or a singular {@link Nothing}. * @example * * const m1 = getArbitraryProperty(context1); * // => Just(context1) * * const m2 = getArbitraryProperty(context2); * // => Just(context2) * * const m3 = getArbitraryProperty(context3); * // => Nothing() * * const m4 = getArbitraryProperty(context4); * // => Nothing() * * Maybe.all([m1, m2]); * // => Just([context1, context2]) * * Maybe.all([m1, m2, m3]); * // => Nothing() * * Maybe.all([m1, m2, m3, m4]); * // => Nothing() */ static all(maybes) { return find(Maybe.isNothing, maybes) || Maybe.of(stream(maybes).map(get("value")).reduce(concat, [])); } /** * Returns the first {@link Just} in the collection or finally a {@link Nothing}. * @static * @member * @param {Maybe[]} maybes - Collection of maybes. * @return {Maybe} First {@link Just} or finally a {@link Nothing}. * @example * * const m1 = getArbitraryProperty(context1); * // => Just(context1) * * const m2 = getArbitraryProperty(context2); * // => Just(context2) * * const m3 = getArbitraryProperty(context3); * // => Nothing() * * const m4 = getArbitraryProperty(context4); * // => Nothing() * * Maybe.any([m1, m2]); * // => Just(context1) * * Maybe.any([m2, m3]); * // => Just(context2) * * Maybe.any([m3, m4]); * // => Nothing() */ static any(maybes) { return find(Maybe.isJust, maybes) || new Nothing(); } /** * Creates a new {@link Maybe} from a <code>value</code>. If the <code>value</code> is already a {@link Maybe} * instance, the <code>value</code> is returned unchanged. Otherwise, a new {@link Just} is made with the * <code>value</code>. * @static * @member * @param {*} value - Value to wrap in a {@link Maybe}. * @return {Maybe} {@link Maybe} when is the <code>value</code> already wrapped or {@link Just} wrapped * <code>value</code>. * * Maybe.from(); * // => Just() * * Maybe.from(true); * // => Just(true) * * Maybe.from(Just.from(value)); * // => Just(value) * * Maybe.from(Nothing.from()); * // => Nothing() */ static from(value) { return this.isMaybe(value) ? value : this.ofNullable(value); } /** * Determines whether or not the value is a {@link Just}. * @static * @member * @param {*} value - Value to check. * @return {Boolean} <code>true</code> for {@link Just}; <code>false</code> for {@link Nothing}. * @example * * isJust(); * // => false * * isJust(null); * // => false * * isJust(Just.from()); * // => true * * isJust(Nothing.from()); * // => false */ static isJust(value) { return value instanceof Just; } /** * Determines whether or not the value is a {@link Maybe}. * @static * @member * @param {*} value - Value to check. * @return {Boolean} <code>true</code> for {@link Maybe}; <code>false</code> for anything else. * @example * * isMaybe(); * // => false * * isMaybe(null); * // => false * * isMaybe(Just.from()); * // => true * * isMaybe(Nothing.from()); * // => true */ static isMaybe(value) { return value instanceof Maybe; } /** * Determines whether or not the value is a {@link Nothing}. * @static * @member * @param {*} value - Value to check. * @return {Boolean} <code>true</code> for {@link Nothing}; <code>false</code> for {@link Just}. * @example * * isNothing(); * // => false * * isNothing(null); * // => false * * isNothing(Nothing.from()); * // => true * * isNothing(Just.from()); * // => false */ static isNothing(value) { return value instanceof Nothing; } /** * Wraps the <code>value</code> in a {@link Just}. No parts of <code>value</code> are checked. * @static * @member * @param {*} value - Value to wrap. * @return {Just} {@link Just} wrapped <code>value</code>. * @example * * Maybe.of(); * // => Just() * * Maybe.of(true); * // => Just(true) * * Maybe.of(Just.from(value)); * // => Just(Just(value)) * * Maybe.of(Nothing.from()); * // => Just(Nothing()) */ static of(value) { return new Just(value); } /** * Wraps the <code>value</code> in a {@link Just} if the value is not <code>null</code>, <code>undefined</code>, or * {@link Nothing}. * @static * @member * @param {*} value - Value to wrap. * @return {Maybe} {@link Just} wrapped <code>value</code> or {@link Nothing}. * @example * * Maybe.ofNullable(); * // => Nothing() * * Maybe.ofNullable(null); * // => Nothing() * * Maybe.ofNullable(true); * // => Just(true) * * Maybe.ofNullable(Just.from(value)); * // => Just(Just(value)) * * Maybe.ofNullable(Nothing.from()); * // => Nothing() */ static ofNullable(value) { return isNull(value) || isUndefined(value) || Maybe.isNothing(value) ? new Nothing() : new Just(value); } /** * Tries to invoke a <code>supplier</code>. The result of the <code>supplier</code> is returned in a * {@link Just}. If an exception is thrown, a {@link Nothing} is returned. The <code>function</code> takes no * arguments. * @static * @member * @param {Supplier} supplier - Function to invoke. * @return {Maybe} {@link Just} wrapped supplier result or {@link Nothing} wrapped <code>error</code>. * @example * * Maybe.try(normalFunction); * // => Just(returnValue) * * Maybe.try(throwableFunction); * // => Nothing() */ static try(method) { try { return Just.from(method()); } catch (error) { return Nothing.from(); } } constructor(value) { this.value = value; } /** * Applies the function contained in the instance of a {@link Just} to the value contained in the provided * {@link Just}, producing a {@link Just} containing the result. If the instance is a {@link Nothing}, the result * is the {@link Nothing} instance. If the instance is a {@link Just} and the provided {@link Maybe} is * {@link Nothing}, the result is the provided {@link Nothing}. * @abstract * @function ap * @memberof Maybe * @instance * @param {Maybe} other - Value to apply to the function wrapped in the {@link Just}. * @return {Maybe} {@link Just} wrapped applied function or {@link Nothing}. * @example <caption>Just#ap</caption> * * const findPerson = curryN(3, Person.find); // Person.find(name, birthdate, address) * * Just.from(findPerson) // => Just(findPerson) * .ap(Just.ofNullable(name)) // => Just(name) * .ap(Just.ofNullable(birthdate)) // => Just(birthdate) * .ap(Just.ofNullable(address)) // => Just(address) * .ifJust(console.log); // => Log Person.find() response */ /** * Applies the provided function to the value contained for a {@link Just}. The function should return the value * wrapped in a {@link Maybe}. If the instance is a {@link Nothing}, the function is ignored and then instance is * returned unchanged. * @abstract * @function chain * @memberof Maybe * @instance * @param {Chain.<Maybe>} method - The function to invoke with the value. * @return {Maybe} {@link Maybe} wrapped value returned by the provided <code>method</code>. * @example <caption>Just#chain</caption> * * // Using lodash/fp/curry and get * const getConfigOption = curry((path, config) => Maybe.ofNullable(get(path, config)); * * Maybe.ofNullable(config) * .chain(getConfigOption("path.to.option")) */ /** * Determines whether or not the <code>other</code> is equal in value to the current (<code>this</code>). This is * <strong>not</strong> a reference check. * @param {*} other - Other value to check. * @return {Boolean} <code>true</code> if the two Maybes are equal; <code>false</code> if not equal. * @example <caption>Reflexivity</caption> * * v1.equals(v1) === true; * // => true * * @example <caption>Symmetry</caption> * * v1.equals(v2) === v2.equals(v1); * // => true * * @example <caption>Transitivity</caption> * * (v1.equals(v2) === v2.equals(v3)) && v1.equals(v3) * // => true */ equals(other) { return isEqual(this, other); } /** * Extends the Maybe. This is used for workflow continuation where the context has shifted. * @abstract * @function extend * @memberof Maybe * @instance * @param {Extend.<Maybe>} - method - The function to invoke with the value. * @return {Maybe} * @example <caption>Workflow continuation</caption> * * // Workflow from makeRequest.js * const makeRequest = requestOptions => requestAsPromise(requestOptions) * .then(Just.from) * .catch(Nothing.from); * * // Workflow from savePerson.js * const savePerson = curry((requestOptions, optionalPerson) => optionalPerson * .map(Person.from) * .map(person => set("body", person, requestOptions)) * .map(makeRequest) * ); * * // Workflow from processResponse.js * const processResponse = optionalResponse => optionalResponse * .ifJust(console.log); * * Maybe.ofNullable(person) * .extend(savePerson({ method: "POST" })) * .extend(processResponse); */ /** * Returns the value if the instance is a {@link Just} otherwise the <code>null</code>. * @function get * @memberof Maybe * @instance * @return {*} * @example <caption>Just#get</caption> * * Just.from(value).get(); * // => value * * @example <caption>Nothing#get</caption> * * Nothing.from().get(); * // => null */ get() { return this.value; } /** * Applies the provided function to the value contain for a {@link Just}. Any return value from the function is * ignored. If the instance is a {@link Nothing}, the function is ignored and the instance is returned. * @abstract * @function ifJust * @memberof Maybe * @instance * @param {Consumer} method - The function to invoke with the value. * @return {Maybe} Current instance. * @example <caption>Just#ifJust</caption> * * Just.from(value).ifJust(doSomething); // doSomething(value) * // => Just(value) * * @example <caption>Nothing#ifJust</caption> * * Nothing.from().ifJust(doSomething); // void * // => Nothing() */ /** * Applies the provided function to the value contain for a {@link Nothing}. Any return value from the function is * ignored. If the instance is a {@link Just}, the function is ignored and the instance is returned. * @abstract * @function ifNothing * @memberof Maybe * @instance * @param {Callable} method - The function to invoke. * @return {Maybe} Current instance. * @example <caption>Just#ifNothing</caption> * * Just.from(value).ifNothing(doSomething); // void * // => Just(value) * * @example <caption>Nothing#ifNothing</caption> * * Nothing.from().ifNothing(doSomething); // doSomething() * // => Nothing() */ /** * Determines whether or not the instance is a {@link Nothing}. * @return {Boolean} <code>true</code> if the instance is a {@link Nothing}; <code>false</code> is not. * @example <caption>Just#isNothing</caption> * * Just.from(value).isNothing(); * // => false * * @example <caption>Nothing#isNothing</caption> * * Nothing.from().isNothing(); * // => true */ isNothing() { return this instanceof Nothing; } /** * Determines whether or not the instance is a {@link Just}. * @return {Boolean} <code>true</code> if the instance is a {@link Just}; <code>false</code> is not. * @example <caption>Just</caption> * * Just.from(value).isNothing(); * // => true * * @example <caption>Nothing#isJust</caption> * * Nothing.from().isNothing(); * // => false */ isJust() { return this instanceof Just; } /** * Applies the provided function to the value contained for a {@link Just} which is, in turn, wrapped in a * {@link Just}. If the instance is a {@link Nothing}, the function is ignored and then instance is returned * unchanged. * @abstract * @function map * @memberof Maybe * @instance * @param {Function} method - The function to invoke with the value. * @return {Maybe} {@link Maybe} wrapped value mapped with the provided <code>method</code>. * @example * * // Using lodash/fp/flow and sort * Just.from([1, 3, 2]).map(flow(sort, join(", "))); * // => Just("1, 2, 3") * * Nothing.from().map(flow(sort, join(", "))); * // => Nothing() */ /** * @see Maybe.ofNullable */ of(value) { return Maybe.of(value); } /** * Returns the value if the instance is a {@link Just} otherwise returns the value supplied if the instance is a * {@link Nothing}. * @abstract * @function orElse * @memberof Maybe * @instance * @param {Consumer} method - The function to invoke with the value. * @return {*} * @example <caption>Just#orElse</caption> * * Just.from(value).orElse(otherValue); * // => value * * @example <caption>Nothing#orElse</caption> * * Nothing.from().orElse(otherValue); * // => otherValue */ /** * Return the value if the instance is a {@link Just} otherwise returns the value from the function provided. * @abstract * @function orElseGet * @memberof Maybe * @instance * @param {Supplier} method - The function supplying the optional value. * @return {*} * @example <caption>Just#orElseGet</caption> * * Just.from(value).orElseGet(getOtherValue); * // => value * * @example <caption>Nothing#orElseGet</caption> * * Nothing.from().orElseGet(getOtherValue); * // => otherValue */ /** * Returns the value if the instance is a {@link Just} otheriwse throws the <code>Error</code> supplied by the * function provided. * @abstract * @function orElseThrow * @memberof Maybe * @instance * @param {Supplier} method - The function to invoke with the value. * @return {*} * @throws {Error} returned by the provided function. * @example <caption>Just#orElseThrow</caption> * * Just.from(value).orElseThrow(createException); * // => value * * @example <caption>Nothing#orElseThrow</caption> * * Nothing.from().orElseThrow(createException); // throw createException() */ /** * Converts the {@link Maybe} to an {@link Either}. {@link Just} becomes a {@link Right} and {@link Nothing} becomes a * {@link Left}. * @abstract * @function toEither * @memberof Maybe * @instance * @param {Either} either - Either implementation. * @return {Either} {@link Either} wrapped <code>value</code>. * @example <caption>Just#toEither</caption> * * const Either = require("lodash-fantasy/data/Either"); * * Just.from(value).toEither(Either); * // => Either.Right(value); * * @example <caption>Nothing#toEither</caption> * * const Either = require("lodash-fantasy/data/Either"); * * Nothing.from().toEither(Either); * // => Either.Left(null); */ /** * Converts the Maybe to a <code>Promise</code> using the provided <code>Promise</code> implementation. * @abstract * @function toPromise * @memberof Maybe * @instance * @param {Promise} promise - Promise implementation. * @return {Promise} <code>Promise</code> wrapped <code>value</code>. * @example <caption>Just#toPromise</caption> * * const Bluebird = require("bluebird"); * * Just.from(value).toPromise(Bluebird); * // => Promise.resolve(value); * * @example <caption>Nothing#toPromise</caption> * * const Bluebird = require("bluebird"); * * Nothing.from().toPromise(Bluebird); * // => Promise.reject(null); */ /** * Returns a <code>String</code> representation of the {@link Maybe}. * @abstract * @function toString * @memberof Maybe * @instance * @return {String} <code>String</code> representation. * @example <caption>Just#toString</caption> * * Just.from(1).toString(); * // => "Maybe.Just(1)" * * @example <caption>Nothing#toString</caption> * * Nothing.from().toString(); * // => "Maybe.Nothing(null)" */ /** * Converts the {@link Maybe} to an {@link Validation}. {@link Just} becomes a {@link Success} and {@link Nothing} * becomes a {@link Failure}. * @abstract * @function toValidation * @memberof Maybe * @instance * @param {Validation} validation - Validation implementation. * @return {Validation} {@link Validation} wrapped <code>value</code>. * @example <caption>Just#toValidation</caption> * * const Validation = require("lodash-fantasy/data/Validation"); * * Just.from(value).toValidation(Validation); * // => Validation.Success(value); * * @example <caption>Nothing#toValidation</caption> * * const Validation = require("lodash-fantasy/data/Validation"); * * Nothing.from().toValidation(Validation); * // => Validation.Failure([null]); */ } /** * Iterates over a collection of maybes and invokes the <code>iteratee</code> for each {@link Maybe}. The * <code>iteratee</code> is invoked with one argument: <code>(value)</code>. Iteratee functions may exit iteration * early by explicitly returning a {@link Nothing}. * @static * @member * @param {Consumer} iteratee - The function to invoke per iteration. * @param {Maybe[]} values - Collection of Maybes over which to iterate. * @return {Maybe[]} Current {@link Maybe} collection. * @example * * const optionalValues = [ * getValue(path1, source), // => Just(value1) * getValue(path2, source), // => Just(value2) * getValue(path3, source), // => Nothing() * getValue(path4, source) // => Nothing() * ]; * * Maybe.each(optionalValue => optionalValue.ifJust(console.log), optionalValues); * // => Just(value1) * // => Just(value2) */ Maybe.each = curry((iteratee, values) => each( flow(iteratee, negate(Maybe.isNothing)), values )); /** * Determines whether or not the <code>other</code> is equal in value to the current (<code>this</code>). This is * <strong>not</strong> a reference check. * @static * @member * @param {*} other - Other value to check. * @return {Boolean} <code>true</code> if the two validations are equal; <code>false</code> if not equal. * @example <caption>Reflexivity</caption> * * Maybe.equals(v1, v1) === true; * // => true * * @example <caption>Symmetry</caption> * * Maybe(v1, v2) === Maybe.equals(v2, v1); * // => true * * @example <caption>Transitivity</caption> * * (Maybe.equals(v1, v2) === Maybe.equals(v2, v3)) && Maybe.equals(v1, v3) * // => true */ Maybe.equals = isEqual; /** * Iterates over a collection of values, returning an array of all values the <code>predicate</code> for which returns * truthy. The <code>predicate</code> is invoked with one argument: <code>(value)</code>. * @static * @member * @param {Predicate} predicate - The function to invoke per iteration. * @param {Maybes[]} values - Collection of values over which to iterate. * @return {Maybes[]} Filtered {@link Maybe} collection. * @example <caption>Filter and log failures</caption> * * const optionalValues = [ * getValue(path1, config), // => Just(value1) * getValue(path2, config), // => Just(value2) * getValue(path3, config), // => Nothing() * getValue(path4, config) // => Nothing() * ]; * * Maybe.filter(Maybe.isJust, optionalValues); * // => [Just(value1), Just(value2)] */ Maybe.filter = filter; /** * Creates an array of values by invoking {@link Maybe#map} with the <code>iteratee</code> for each {@link Maybe} in the * collection. The iteratee is invoked with one argument: <code>(value)</code>. * @static * @member * @param {Function} iteratee - The function to invoke per iteration. * @param {Maybe[]} values - Collection of values over which to iterate. * @return {Maybe[]} Mapped {@link Maybe} collection. * @example <caption>Mapping each Maybe's value</caption> * * const optionalValues = [ * getValue(path1, config), // => Just(1.5) * getValue(path2, config), // => Just(2.25) * getValue(path3, config), // => Nothing() * getValue(path4, config) // => Nothing() * ]; * * Maybe.mapIn(Math.floor, optionalValues); * // => [Just(1), Just(2), Nothing(), Nothing()] */ Maybe.mapIn = curry((iteratee, values) => map(invokeIn("map", iteratee), values)); /** * Creates an array of values by running each {@link Maybe} in collection through the <code>iteratee</code>. The * iteratee is invoked with one argument: <code>(value)</code>. * @static * @member * @param {Function} iteratee - The function to invoke per iteration. * @param {Maybe[]} values - Collection of values over which to iterate. * @return {Maybe[]} Mapped collection. * @example <caption>Mapping all values to promises</caption> * * const optionalValues = [ * getValue(path1, config), // => Just(value1) * getValue(path2, config), // => Just(value2) * getValue(path3, config), // => Nothing() * getValue(path4, config) // => Nothing() * ]; * * Maybe.map(Maybe.toPromise, optionalValues); * // => [Promise.resolve(price1), Promise.resolve(price2), Promise.reject(null), Promise.reject(null)] */ Maybe.map = map; /** * Reduces collection to a value which is the accumulated result of running each value in the <code>values</code> * collection through the <code>iteratee</code>, where each successive invocation is supplied the return value of the * previous. The iteratee is invoked with two arguments: <code>(accumulator, value)</code>. * @static * @member * @param {Reduction} iteratee - The function to invoke per iteration. * @param {*} accumulator - The initial value. * @param {Maybe[]} values - Collection of values over which to iterate. * @return {*} Accumulator. * @example * * const optionalValues = [ * getValue(path1, config), // => Just(value1) * getValue(path2, config), // => Just(value2) * getValue(path3, config), // => Nothing() * getValue(path4, config) // => Nothing() * ]; * * // Using lodash/fp/concat * Maybe.reduce( * (result, value) => value.isJust() ? concat(result, value.get()) : result, * [], * optionalValues * ); * // => [value1, value2] */ Maybe.reduce = reduce; /** * Converts a {@link Maybe} to a {@link Either}. {@link Just} becomes a {@link Right} and {@link Nothing} becomes a * {@link Left}. * @static * @member * @param {Either} either - Either implementation. * @param {Maybe} value - Maybe to convert. * @return {Either} {@link Either} wrapped <code>value</code>. * @example <caption>Just to Right</caption> * * Maybe.toEither(Either, Just.from(value)); * // => Either.Right(value); * * @example <caption>Nothing to Left</caption> * * Maybe.toEither(Either, Nothing.from()); * // => Either.Left(null); */ Maybe.toEither = invokeIn("toEither"); /** * Converts a validation to a <code>Promise</code> using the provided <code>Promise</code> implementation. * @static * @member * @param {Promise} promise - Promise implementation. * @param {Maybe} value - Maybe to convert. * @return {Promise} <code>Promise</code> wrapped <code>value</code>. * @example <caption>Convert with bluebird's implementation of Promise</caption> * * const toBluebird = Maybe.toPromise(require("bluebird")); * * toBluebird(Just.from(value)); * // => Promise.resolve(value); * * toBluebird(Nothing.from()); * // => Promise.reject(null); */ Maybe.toPromise = invokeIn("toPromise"); /** * Converts a {@link Maybe} to a {@link Validation}. {@link Just} becomes a {@link Success} and {@link Nothing} becomes * a {@link Failure}. * @static * @member * @param {Validation} validation - Validation implementation. * @param {Maybe} value - Maybe to convert. * @return {Validation} {@link Validation} wrapped <code>value</code>. * @example <caption>Just to Success</caption> * * Maybe.toValidation(Validation, Just.from(value)); * // => Validation.Success(value); * * @example <caption>Nothing to Failure</caption> * * Maybe.toValidation(Validation, Nothing.from()); * // => Validation.Failure(null); */ Maybe.toValidation = invokeIn("toValidation"); /** * @extends Maybe * @inheritdoc */ class Just extends Maybe { /** * Creates a new {@link Just} from a <code>value</code>. If the <code>value</code> is already a {@link Maybe} * instance, the <code>value</code> is returned unchanged. Otherwise, a new {@link Just} is made with the * <code>value</code>. * @static * @param {*} value - Value to wrap in a {@link Just}. * @return {Maybe} {@link Maybe} when is the <code>value</code> already wrapped or {@link Just} wrapped * <code>value</code>. * @example <caption>Just from nothing</caption> * * Just.from(); * // => Just() * * @example <caption>Just from arbitrary value</caption> * * Just.from(true); * // => Just(true) * * @example <caption>Just from another Just</caption> * * Just.from(Just.from(value)); * // => Just(value) * * @example <caption>Just from Nothing</caption> * * Just.from(Nothing.from()); * // => Nothing() */ static from(value) { return Maybe.isMaybe(value) ? value : new Just(value); } constructor(value) { super(value); } ap(other) { return other.map(this.value); } chain(method) { return Maybe.from(method(this.value)); } extend(method) { return Maybe.from(method(this)); } ifJust(method) { method(this.value); return this; } ifNothing() { return this; } map(method) { return Just.ofNullable(method(this.value)); } orElse() { return this.value; } orElseGet() { return this.value; } orElseThrow() { return this.value; } toEither(either) { return new either.Right(this.value); } toPromise(promise) { return promise.resolve(this.value); } toString() { return `Maybe.Just(${this.value})`; } toValidation(validation) { return new validation.Success(this.value); } } /** * @extends Maybe * @inheritdoc */ class Nothing extends Maybe { /** * Creates a new {@link Nothing} from a <code>value</code>. If the <code>value</code> is already a {@link Maybe} * instance, the <code>value</code> is returned unchanged. Otherwise, a new {@link Nothing} is made with the * <code>value</code>. * @static * @param {*} value - Value to wrap in a {@link Nothing}. * @return {Maybe} {@link Maybe} when is the <code>value</code> already wrapped or {@link Nothing} wrapped * <code>value</code>. * @example <caption>Nothing from nothing</caption> * * Nothing.from(); * // => Nothing() * * @example <caption>Nothing from arbitrary value</caption> * * Nothing.from(true); * // => Nothing() * * @example <caption>Nothing from Just</caption> * * Nothing.from(Just.from(value)); * // => Just.from(value) * * @example <caption>Nothing from another Nothing</caption> * * Nothing.from(Nothing.from()); * // => Nothing() */ static from(value) { return Maybe.isMaybe(value) ? value : new Nothing(); } constructor() { super(null); } ap() { return this; } chain() { return this; } extend() { return this; } ifJust() { return this; } ifNothing(method) { method(); return this; } map() { return this; } orElse(value) { return value; } orElseGet(method) { return method(); } orElseThrow(method) { throw method(); } toEither(either) { return new either.Left(this.value); } toPromise(promise) { return promise.reject(this.value); } toString() { return "Maybe.Nothing(null)"; } toValidation(validation) { return new validation.Failure(this.value); } } module.exports = Maybe;