typescript-monads
Version:
Write cleaner TypeScript
1,270 lines (1,253 loc) • 120 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var rxjs = require('rxjs');
var operators = require('rxjs/operators');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
function maybe(value) {
return new Maybe(value);
}
function none() {
return Maybe.none();
}
function some(value) {
return maybe(value);
}
/**
* Creates a function that returns a Maybe for the given property path.
*
* This is a powerful utility for safely navigating nested object structures.
* It creates a type-safe property accessor function that returns a Maybe
* containing the value at the specified path if it exists, or None if any
* part of the path is missing.
*
* @param path A dot-separated string path to the desired property
* @returns A function that takes an object and returns a Maybe of the property value
*
* @example
* const getEmail = maybeProps<User>('profile.contact.email');
*
* // Later in code
* const emailMaybe = getEmail(user);
* // Returns Some(email) if user.profile.contact.email exists
* // Returns None if any part of the path is undefined/null
*
* // Use with filter
* const validEmail = getEmail(user).filter(email => email.includes('@'));
*
* // Use with match
* getEmail(user).match({
* some: email => sendVerification(email),
* none: () => showEmailPrompt()
* });
*/
function maybeProps(path) {
var segments = path.split('.');
return function (obj) {
var e_1, _a;
var current = obj;
try {
for (var segments_1 = __values(segments), segments_1_1 = segments_1.next(); !segments_1_1.done; segments_1_1 = segments_1.next()) {
var segment = segments_1_1.value;
if (current === null || current === undefined || !(segment in current)) {
return none();
}
current = current[segment];
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (segments_1_1 && !segments_1_1.done && (_a = segments_1.return)) _a.call(segments_1);
}
finally { if (e_1) throw e_1.error; }
}
return maybe(current);
};
}
var Result = /** @class */ (function () {
function Result() {
}
Result.ok = function (value) {
return new OkResult(value);
};
Result.fail = function (value) {
return new FailResult(value);
};
/**
* Creates a Result from a Promise.
*
* Creates a Promise that will resolve to a Result that is:
* - Ok containing the resolved value if the promise resolves successfully
* - Fail containing the rejection reason if the promise rejects
*
* This static method makes it easy to convert Promise-based APIs to Result-based
* error handling, giving you more explicit control flow and type safety.
*
* @param promise The promise to convert to a Result
* @returns A Promise that resolves to a Result containing either the value or error
*
* @example
* // Convert a promise to a Result
* const resultPromise = Result.fromPromise(fetchData());
*
* resultPromise.then(result => {
* result.match({
* ok: data => renderData(data),
* fail: error => showError(error)
* });
* });
*
* // With Promise chaining
* Result.fromPromise(fetchData())
* .then(result => {
* if (result.isOk()) {
* const data = result.unwrap();
* return renderData(data);
* } else {
* const error = result.unwrapFail();
* return showError(error);
* }
* });
*/
Result.fromPromise = function (promise) {
return promise
.then(function (value) { return new OkResult(value); })
.catch(function (error) { return new FailResult(error); });
};
/**
* Creates a Result from an Observable.
*
* Creates a Promise that will resolve to a Result that is:
* - Ok containing the first emitted value if the observable emits a value
* - Fail containing the provided error if the observable completes without emitting
* - Fail containing the error if the observable errors
*
* This static method bridges the reactive Observable world with the Result monad,
* providing a way to handle emissions, completion, and errors in a functional style.
*
* Note that this transformation changes the timing model from continuous/reactive
* to a one-time asynchronous result. Only the first emission is captured, and the
* observable is no longer reactive after transformation.
*
* @param observable The observable to convert to a Result
* @param defaultError The error to use if the observable completes without emitting
* @returns A Promise that resolves to a Result containing either the value or error
*
* @requires rxjs@^7.0
* @example
* // Convert an observable to a Result
* Result.fromObservable(
* userService.getUser(userId),
* new Error('User not found')
* ).then(result => {
* result.match({
* ok: user => renderUser(user),
* fail: error => showUserNotFound(error)
* });
* });
*/
Result.fromObservable = function (observable, defaultError) {
return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('rxjs')); }).then(function (_a) {
var firstValueFrom = _a.firstValueFrom, take = _a.take, map = _a.map, catchError = _a.catchError;
return firstValueFrom(observable.pipe(take(1), map(function (value) { return new OkResult(value); }), catchError(function (error) {
// Return the error from the observable directly rather than using EMPTY
return [new FailResult(error)];
}))).then(function (result) { return result; }, function () { return new FailResult(defaultError); } // Handle the case where firstValueFrom rejects
);
});
};
/**
* Transforms an array of Result values into a Result containing an array of values.
*
* If all Results in the input array are Ok, returns an Ok Result containing an array of all values.
* If any Result in the input array is Fail, returns a Fail Result containing the first error encountered.
*
* This is similar to how Promise.all works but for Results, allowing you to combine
* multiple Results and propagate errors if any occur.
*
* @param results An array of Result values
* @returns A Result containing either an array of all Ok values or the first Fail error
*
* @example
* // All Results are Ok
* const result1 = Result.sequence([
* ok(1),
* ok(2),
* ok(3)
* ]);
* // result1 is Ok([1, 2, 3])
*
* // One Result is Fail
* const result2 = Result.sequence([
* ok(1),
* fail(new Error('Failed')),
* ok(3)
* ]);
* // result2 is Fail(Error('Failed'))
*/
Result.sequence = function (results) {
var e_1, _a;
if (results.length === 0) {
return new OkResult([]);
}
var values = [];
try {
for (var results_1 = __values(results), results_1_1 = results_1.next(); !results_1_1.done; results_1_1 = results_1.next()) {
var r = results_1_1.value;
if (r.isFail()) {
return new FailResult(r.unwrapFail());
}
values.push(r.unwrap());
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (results_1_1 && !results_1_1.done && (_a = results_1.return)) _a.call(results_1);
}
finally { if (e_1) throw e_1.error; }
}
return new OkResult(values);
};
/**
* Alias for sequence, transforms an array of Result values into a Result containing an array of values.
*
* If all Results in the input array are Ok, returns an Ok Result containing an array of all values.
* If any Result in the input array is Fail, returns a Fail Result containing the first error encountered.
*
* Named to align with Promise.all for familiarity.
*
* @param results An array of Result values
* @returns A Result containing either an array of all Ok values or the first Fail error
*
* @example
* // All Results are Ok
* const result1 = Result.all([
* ok(1),
* ok(2),
* ok(3)
* ]);
* // result1 is Ok([1, 2, 3])
*
* // One Result is Fail
* const result2 = Result.all([
* ok(1),
* fail(new Error('Failed')),
* ok(3)
* ]);
* // result2 is Fail(Error('Failed'))
*/
Result.all = function (results) {
return Result.sequence(results);
};
return Result;
}());
var OkResult = /** @class */ (function (_super) {
__extends(OkResult, _super);
function OkResult(successValue) {
var _this = _super.call(this) || this;
_this.successValue = successValue;
return _this;
}
/**
* Returns true as this is an Ok Result variant.
*
* This implementation satisfies the abstract method from the Result class
* and serves as a TypeScript type guard, allowing TypeScript to narrow the
* type to OkResult when `isOk()` returns true.
*
* @returns true (always, for OkResult instances)
*/
OkResult.prototype.isOk = function () {
return true;
};
/**
* Returns false as this is not a Fail Result variant.
*
* This implementation satisfies the abstract method from the Result class
* and serves as a TypeScript type guard that will never narrow the type
* to FailResult for an OkResult instance.
*
* @returns false (always, for OkResult instances)
*/
OkResult.prototype.isFail = function () {
return false;
};
/**
* Extracts the contained Ok value.
*
* Since this is an OkResult, this method safely returns the contained value
* without any risk of exceptions.
*
* @returns The contained Ok value
*/
OkResult.prototype.unwrap = function () {
return this.successValue;
};
/**
* Extracts the contained Ok value or returns a default.
*
* Since this is an OkResult, this method simply returns the contained
* value and ignores the default value parameter.
*
* @param opt The default value (not used in OkResult implementation)
* @returns The contained Ok value
*/
OkResult.prototype.unwrapOr = function () {
return this.unwrap();
};
/**
* Attempts to extract the contained Fail value, but throws since this is an OkResult.
*
* This method is unsafe to call on an OkResult and will always throw an exception.
*
* @throws ReferenceError Always throws with message 'Cannot unwrap a success as a failure'
* @returns Never returns a value, always throws
*/
OkResult.prototype.unwrapFail = function () {
throw new ReferenceError('Cannot unwrap a success as a failure');
};
/**
* Converts this Ok Result to a Some Maybe containing the success value.
*
* This method transforms the Ok Result into a Maybe, focusing on the success path.
* It always returns a Some Maybe for OkResult instances.
*
* @returns A Some Maybe containing the non-nullable success value
*/
OkResult.prototype.maybeOk = function () {
return maybe(this.successValue);
};
/**
* Converts this Ok Result to a None Maybe.
*
* This method transforms the Ok Result into a Maybe, focusing on the failure path.
* Since this is an OkResult with no error value, it always returns a None Maybe.
*
* @returns A None Maybe (always, for OkResult instances)
*/
OkResult.prototype.maybeFail = function () {
return none();
};
/**
* Applies the success branch of a pattern matching object to this Ok Result.
*
* This method provides a functional way to handle the Ok variant specifically.
* For OkResult instances, only the 'ok' function of the pattern is called.
*
* @typeParam M - The return type of the pattern matching functions
* @param fn - An object containing functions to handle each Result variant
* @returns The result of applying the 'ok' function to the contained value
*/
OkResult.prototype.match = function (fn) {
return fn.ok(this.successValue);
};
/**
* Maps the Ok value using the provided function.
*
* For OkResult instances, this transforms the contained value using the provided
* function and returns a new OkResult with the transformed value.
*
* @typeParam M - The type of the mapped value
* @param fn - A function that transforms the Ok value
* @returns A new OkResult with the transformed value
*/
OkResult.prototype.map = function (fn) {
return Result.ok(fn(this.successValue));
};
/**
* Maps the Fail value using the provided function, which is a no-op for OkResult.
*
* For OkResult instances, this method ignores the mapping function since there is
* no error value to transform. It returns a new OkResult with the same success value
* but with the new error type parameter.
*
* @typeParam M - The type of the mapped error (only changes the type parameter)
* @param fn - A function that would transform the Fail value (not used in OkResult)
* @returns A new OkResult with the same success value and updated error type
*/
OkResult.prototype.mapFail = function () {
return Result.ok(this.successValue);
};
/**
* Chains a function that returns another Result, applying it to the contained value.
*
* This is the monadic bind operation for Result. For OkResult instances, it applies
* the function to the contained value and returns the resulting Result directly.
*
* @typeParam M - The type of the value in the returned Result
* @param fn - A function that takes the Ok value and returns a new Result
* @returns The Result returned by applying the function to the contained value
*/
OkResult.prototype.flatMap = function (fn) {
return fn(this.successValue);
};
/**
* Maps the success value to a Maybe, and flattens the resulting structure.
*
* Since this is an Ok Result, the function is applied to the contained value.
* The result depends on whether the Maybe is Some or None:
* - If Some: Returns an Ok Result with the unwrapped value
* - If None: Returns a Fail Result with the provided error
*
* This implementation follows the monadic bind operation pattern where we:
* 1. Apply the function to get a Maybe
* 2. Match on the Maybe to convert it back to a Result
*
* @param fn Function mapping the contained value to a Maybe
* @param err Error value to use if the Maybe is None
* @returns Either an Ok Result with the unwrapped value or a Fail Result with the provided error
*/
OkResult.prototype.flatMapMaybe = function (fn, err) {
return fn(this.successValue).match({
some: function (val) { return Result.ok(val); },
none: function () { return Result.fail(err); }
});
};
/**
* Converts this Ok Result into a Fail Result using a transformation function.
*
* For OkResult instances, this method applies the function to the contained value
* to generate an error and returns a new Fail Result with that error.
*
* @param fn - A function that transforms the Ok value into a Fail value
* @returns A Fail Result with the error generated from the contained value
*/
OkResult.prototype.toFailWhenOk = function (fn) {
return Result.fail(fn(this.successValue));
};
/**
* Converts this Ok Result into a Fail Result using a provided error value.
*
* For OkResult instances, this method ignores the contained value and returns
* a new Fail Result with the provided error value.
*
* @param val - The error value to use in the returned Fail Result
* @returns A Fail Result containing the provided error
*/
OkResult.prototype.toFailWhenOkFrom = function (val) {
return Result.fail(val);
};
/**
* Executes a side-effect function for this Ok Result.
*
* For OkResult instances, this method calls the 'ok' function if provided.
* The 'fail' function is never called, even if provided.
*
* @param val - An object containing optional functions for Ok and Fail variants
*/
OkResult.prototype.tap = function (val) {
typeof val.ok === 'function' && val.ok(this.successValue);
};
/**
* Executes a side-effect function with the contained Ok value.
*
* For OkResult instances, this method always calls the provided function
* with the contained value.
*
* @param fn - A function to execute with the Ok value
*/
OkResult.prototype.tapOk = function (fn) {
fn(this.successValue);
};
/**
* No-op method for consistency with the Result interface.
*
* For OkResult instances, this method does nothing since there is no error
* value to operate on.
*/
OkResult.prototype.tapFail = function () { };
/**
* No-op method that returns this Result for chaining.
*
* For OkResult instances, this method simply returns the current Result
* without calling any function since there is no error value to operate on.
*
* @returns This Result unchanged
*/
OkResult.prototype.tapFailThru = function () {
return this;
};
/**
* Executes a side-effect function with the Ok value and returns this Result for chaining.
*
* For OkResult instances, this method calls the provided function with the
* contained value and then returns the original Result unchanged.
*
* @param fn - A function to execute with the Ok value
* @returns This Result unchanged
*/
OkResult.prototype.tapOkThru = function (fn) {
this.tapOk(fn);
return this;
};
/**
* Executes a side-effect function and returns this Result for chaining.
*
* For OkResult instances, this method calls the 'ok' function if provided
* and then returns the original Result unchanged.
*
* @param val - An object containing optional functions for Ok and Fail variants
* @returns This Result unchanged
*/
OkResult.prototype.tapThru = function (val) {
this.tap(val);
return this;
};
/**
* No-op for OkResult, returns this Result unchanged.
*
* Since this is already an OkResult, there's no need to recover from an error.
* This method simply returns the current Result.
*
* @returns This Result unchanged
*/
OkResult.prototype.recover = function () {
return this;
};
/**
* No-op for OkResult, returns this Result unchanged.
*
* Since this is already an OkResult, there's no need to recover with another Result.
* This method simply returns the current Result.
*
* @returns This Result unchanged
*/
OkResult.prototype.recoverWith = function () {
return this;
};
/**
* Returns this Result since it's already an Ok variant.
*
* For OkResult instances, this method ignores the fallback Result and
* returns the current Result unchanged.
*
* @returns This Result unchanged
*/
OkResult.prototype.orElse = function () {
return this;
};
/**
* Swaps the Ok and Fail values, creating a new Fail Result.
*
* For OkResult instances, this method transforms the contained success value
* into an error and returns a new Fail Result with that error.
*
* @returns A new Fail Result with the success value as an error
*/
OkResult.prototype.swap = function () {
return Result.fail(this.successValue);
};
/**
* Combines this Result with another Result using a combining function.
*
* For OkResult instances, this method applies the function to both values
* if the other Result is also Ok, or returns the other Result if it's a Fail.
*
* @param other - Another Result to combine with this one
* @param fn - A function that combines the two Ok values
* @returns A new Result containing either the combined values or the error from the other Result
*/
OkResult.prototype.zipWith = function (other, fn) {
var _this = this;
return other.flatMap(function (otherValue) { return Result.ok(fn(_this.successValue, otherValue)); });
};
/**
* Maps the Ok value of this Result to a Promise, and then flattens the resulting structure.
*
* For OkResult instances, this method applies the function to the contained value,
* awaits the Promise, and wraps the resolved value in a new Ok Result.
* If the Promise rejects, it returns a Fail Result with the rejection reason.
*
* @param fn - A function that takes the Ok value and returns a Promise
* @returns A Promise that resolves to a new Result
*/
OkResult.prototype.flatMapPromise = function (fn) {
return fn(this.successValue)
.then(function (value) { return Result.ok(value); })
.catch(function (error) { return Result.fail(error); });
};
/**
* Maps the Ok value of this Result to an Observable, and then flattens the resulting structure.
*
* For OkResult instances, this method applies the function to the contained value,
* subscribes to the Observable, and wraps the first emitted value in a new Ok Result.
* If the Observable errors, it returns a Fail Result with the error.
* If the Observable completes without emitting, it returns a Fail Result with the provided default error.
*
* @param fn - A function that takes the Ok value and returns an Observable
* @param defaultError - The error to use if the Observable completes without emitting
* @returns A Promise that resolves to a new Result
*
* @requires rxjs@^7.0
*/
OkResult.prototype.flatMapObservable = function (fn, defaultError) {
var _this = this;
return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('rxjs')); }).then(function (_a) {
var firstValueFrom = _a.firstValueFrom, take = _a.take, map = _a.map, catchError = _a.catchError;
return firstValueFrom(fn(_this.successValue).pipe(take(1), map(function (value) { return Result.ok(value); }), catchError(function (error) {
// Return the error from the observable directly rather than using EMPTY
return [Result.fail(error)];
}))).then(function (result) { return result; }, function () { return Result.fail(defaultError); } // Handle the case where firstValueFrom rejects
);
});
};
return OkResult;
}(Result));
var FailResult = /** @class */ (function (_super) {
__extends(FailResult, _super);
function FailResult(failureValue) {
var _this = _super.call(this) || this;
_this.failureValue = failureValue;
return _this;
}
/**
* Returns false as this is not an Ok Result variant.
*
* This implementation satisfies the abstract method from the Result class
* and serves as a TypeScript type guard that will never narrow the type
* to OkResult for a FailResult instance.
*
* @returns false (always, for FailResult instances)
*/
FailResult.prototype.isOk = function () {
return false;
};
/**
* Returns true as this is a Fail Result variant.
*
* This implementation satisfies the abstract method from the Result class
* and serves as a TypeScript type guard, allowing TypeScript to narrow the
* type to FailResult when `isFail()` returns true.
*
* @returns true (always, for FailResult instances)
*/
FailResult.prototype.isFail = function () {
return true;
};
/**
* Attempts to extract the contained Ok value, but throws since this is a FailResult.
*
* This method is unsafe to call on a FailResult and will always throw an exception.
*
* @throws Error Always throws with message 'Cannot unwrap a failure'
* @returns Never returns a value, always throws
*/
FailResult.prototype.unwrap = function () {
throw new Error('Cannot unwrap a failure');
};
/**
* Extracts the contained Ok value or returns a default.
*
* Since this is a FailResult, this method always returns the provided default
* value because there is no success value to extract.
*
* @param opt The default value to return
* @returns The provided default value
*/
FailResult.prototype.unwrapOr = function (opt) {
return opt;
};
/**
* Extracts the contained Fail value.
*
* Since this is a FailResult, this method safely returns the contained error
* without any risk of exceptions.
*
* @returns The contained Fail value
*/
FailResult.prototype.unwrapFail = function () {
return this.failureValue;
};
/**
* Converts this Fail Result to a None Maybe.
*
* This method transforms the Fail Result into a Maybe, focusing on the success path.
* Since this is a FailResult with no success value, it always returns a None Maybe.
*
* @returns A None Maybe (always, for FailResult instances)
*/
FailResult.prototype.maybeOk = function () {
return none();
};
/**
* Converts this Fail Result to a Some Maybe containing the error value.
*
* This method transforms the Fail Result into a Maybe, focusing on the failure path.
* It always returns a Some Maybe for FailResult instances.
*
* @returns A Some Maybe containing the error value
*/
FailResult.prototype.maybeFail = function () {
return maybe(this.failureValue);
};
/**
* Applies the failure branch of a pattern matching object to this Fail Result.
*
* This method provides a functional way to handle the Fail variant specifically.
* For FailResult instances, only the 'fail' function of the pattern is called.
*
* @typeParam M - The return type of the pattern matching functions
* @param fn - An object containing functions to handle each Result variant
* @returns The result of applying the 'fail' function to the contained error
*/
FailResult.prototype.match = function (fn) {
return fn.fail(this.failureValue);
};
/**
* Maps the Fail value using the provided function.
*
* For FailResult instances, this transforms the contained error using the provided
* function and returns a new FailResult with the transformed error.
*
* @typeParam M - The type of the mapped error
* @param fn - A function that transforms the Fail value
* @returns A new FailResult with the transformed error
*/
FailResult.prototype.mapFail = function (fn) {
return Result.fail(fn(this.failureValue));
};
/**
* Maps the Ok value using the provided function, which is a no-op for FailResult.
*
* For FailResult instances, this method ignores the mapping function since there is
* no success value to transform. It returns a new FailResult with the same error value
* but with the new success type parameter.
*
* @typeParam M - The type of the mapped value (only changes the type parameter)
* @returns A new FailResult with the same error and updated success type
*/
FailResult.prototype.map = function () {
return Result.fail(this.failureValue);
};
/**
* Chains a function that returns another Result, which is a no-op for FailResult.
*
* For FailResult instances, this method ignores the mapping function since there
* is no success value to transform. It returns a new FailResult with the same error
* but with the new success type parameter.
*
* This follows the monadic law that operations on failures should not execute the transformation.
*
* @typeParam M - The type of the value in the returned Result (only changes the type parameter)
* @returns A FailResult with the same error and updated success type
*/
FailResult.prototype.flatMap = function () {
return Result.fail(this.failureValue);
};
/**
* Short-circuits the flatMapMaybe operation for Fail Results.
*
* Since this is a Fail Result, the function is not applied and the original error is preserved.
* This follows the monadic law that operations on failures should not execute the transformation.
*
* @returns A Fail Result containing the original error
*/
FailResult.prototype.flatMapMaybe = function () {
return Result.fail(this.failureValue);
};
/**
* No-op method for consistency with the Result interface.
*
* For FailResult instances, this method simply returns the current Result
* unchanged since it's already a Fail variant.
*
* @returns This Result unchanged
*/
FailResult.prototype.toFailWhenOk = function () {
return this;
};
/**
* Converts this Fail Result into a new Fail Result with the provided error value.
*
* For FailResult instances, this method returns a new Fail Result with the provided
* error value, replacing the original error.
*
* @param val - The new error value to use
* @returns A Fail Result containing the provided error
*/
FailResult.prototype.toFailWhenOkFrom = function (val) {
return Result.fail(val);
};
/**
* Executes a side-effect function for this Fail Result.
*
* For FailResult instances, this method calls the 'fail' function if provided.
* The 'ok' function is never called, even if provided.
*
* @param val - An object containing optional functions for Ok and Fail variants
*/
FailResult.prototype.tap = function (val) {
typeof val.fail === 'function' && val.fail(this.failureValue);
};
/**
* No-op method for consistency with the Result interface.
*
* For FailResult instances, this method does nothing since there is no success
* value to operate on.
*/
FailResult.prototype.tapOk = function () { };
/**
* Executes a side-effect function with the contained Fail value.
*
* For FailResult instances, this method always calls the provided function
* with the contained error value.
*
* @param fn - A function to execute with the Fail value
*/
FailResult.prototype.tapFail = function (fn) {
fn(this.failureValue);
};
/**
* Executes a side-effect function with the Fail value and returns this Result for chaining.
*
* For FailResult instances, this method calls the provided function with the
* contained error value and then returns the original Result unchanged.
*
* @param fn - A function to execute with the Fail value
* @returns This Result unchanged
*/
FailResult.prototype.tapFailThru = function (fn) {
this.tapFail(fn);
return this;
};
/**
* No-op method that returns this Result for chaining.
*
* For FailResult instances, this method simply returns the current Result
* without calling any function since there is no success value to operate on.
*
* @returns This Result unchanged
*/
FailResult.prototype.tapOkThru = function () {
return this;
};
/**
* Executes a side-effect function and returns this Result for chaining.
*
* For FailResult instances, this method calls the 'fail' function if provided
* and then returns the original Result unchanged.
*
* @param val - An object containing optional functions for Ok and Fail variants
* @returns This Result unchanged
*/
FailResult.prototype.tapThru = function (val) {
this.tap(val);
return this;
};
/**
* Transforms this Fail Result into an Ok Result using a recovery function.
*
* For FailResult instances, this method applies the function to the contained error
* to generate a recovery value and returns a new Ok Result with that value.
*
* @param fn - A function that transforms the Fail value into a recovery value
* @returns A new Ok Result with the recovered value
*/
FailResult.prototype.recover = function (fn) {
return Result.ok(fn(this.failureValue));
};
/**
* Transforms this Fail Result by applying a function that returns another Result.
*
* For FailResult instances, this method applies the function to the contained error,
* which returns a new Result.
*
* @param fn - A function that takes the Fail value and returns a new Result
* @returns The Result returned by the function
*/
FailResult.prototype.recoverWith = function (fn) {
return fn(this.failureValue);
};
/**
* Returns the provided fallback Result since this is a Fail variant.
*
* For FailResult instances, this method returns the provided fallback Result
* instead of the current Result.
*
* @param fallback - The Result to return instead of this one
* @returns The provided fallback Result
*/
FailResult.prototype.orElse = function (fallback) {
return fallback;
};
/**
* Swaps the Ok and Fail values, creating a new Ok Result.
*
* For FailResult instances, this method transforms the contained error
* into a value and returns a new Ok Result with that value.
*
* @returns A new Ok Result with the error as a value
*/
FailResult.prototype.swap = function () {
return Result.ok(this.failureValue);
};
/**
* No-op for FailResult, returns this Result unchanged.
*
* For FailResult instances, this method short-circuits and returns the
* current Result without calling the function, since there's no Ok value
* to combine with the other Result.
*
* @returns This Result unchanged
*/
FailResult.prototype.zipWith = function () {
return Result.fail(this.failureValue);
};
/**
* No-op for FailResult, returns a Promise that resolves to this Result.
*
* For FailResult instances, this method short-circuits and returns a Promise
* that resolves to the current Result without calling the function, since
* there's no Ok value to transform.
*
* @returns A Promise that resolves to this Result
*/
FailResult.prototype.flatMapPromise = function () {
return Promise.resolve(Result.fail(this.failureValue));
};
/**
* No-op for FailResult, returns a Promise that resolves to this Result.
*
* For FailResult instances, this method short-circuits and returns a Promise
* that resolves to the current Result without calling the function, since
* there's no Ok value to transform.
*
* @returns A Promise that resolves to this Result
*/
FailResult.prototype.flatMapObservable = function () {
return Promise.resolve(Result.fail(this.failureValue));
};
return FailResult;
}(Result));
var Maybe = /** @class */ (function () {
function Maybe(value) {
this.value = value;
}
Maybe.prototype.of = function (value) {
return new Maybe(value);
};
Maybe.none = function () {
return new Maybe();
};
Maybe.some = function (value) {
return new Maybe(value);
};
/**
* Creates a Maybe from a Promise.
*
* Creates a Maybe that will resolve to:
* - Some containing the resolved value if the promise resolves successfully
* - None if the promise rejects or resolves to null/undefined
*
* @param promise The promise to convert to a Maybe
* @returns A Promise that resolves to a Maybe containing the result
*
* @example
* // Convert a promise to a Maybe
* Maybe.fromPromise(api.fetchUser(userId))
* .then(userMaybe => userMaybe.match({
* some: user => console.log(user.name),
* none: () => console.log('User not found')
* }));
*/
/**
* Creates a Maybe from a Promise.
*
* Creates a Promise that will resolve to a Maybe that is:
* - Some containing the resolved value if the promise resolves successfully to a non-nullish value
* - None if the promise rejects or resolves to null/undefined
*
* Note on resolution preservation: This static method maps the Promise resolution semantics
* to the Maybe context in a natural way:
* - Promise resolution (success) becomes Some (presence of value)
* - Promise rejection (failure) becomes None (absence of value)
*
* This provides a clean way to convert from error-based to optional-based handling,
* which is often more appropriate for values that might legitimately be missing.
*
* @param promise The promise to convert to a Maybe
* @returns A Promise that resolves to a Maybe containing the result
*
* @example
* // Convert a promise to a Maybe and use in a chain
* Maybe.fromPromise(api.fetchUser(userId))
* .then(userMaybe => userMaybe.match({
* some: user => renderUser(user),
* none: () => showUserNotFound()
* }));
*/
Maybe.fromPromise = function (promise) {
return promise
.then(function (value) { return new Maybe(value); })
.catch(function () { return new Maybe(); });
};
/**
* Creates a Maybe from an Observable.
*
* Creates a Promise that will resolve to a Maybe that is:
* - Some containing the first emitted value if the observable emits a non-nullish value
* - None if the observable completes without emitting, errors, or emits a nullish value
*
* Note on resolution transformation: This method transforms the reactive semantics of
* an Observable to the optional semantics of a Maybe:
* - Observable emissions (data) become Some values (presence)
* - Observable completion without emissions (empty success) becomes None (absence)
* - Observable errors (failure) become None (absence)
*
* Note on timing model: This transformation changes from a continuous/reactive model
* to a one-time asynchronous result. Only the first emission is captured, and the
* reactive nature of the Observable is lost after transformation.
*
* @param observable The observable to convert to a Maybe
* @returns A Promise that resolves to a Maybe containing the first emitted value
*
* @requires rxjs@^7.0
* @example
* // Convert an observable to a Maybe and use in a chain
* Maybe.fromObservable(userService.getUser(userId))
* .then(userMaybe => userMaybe
* .map(user => user.name)
* .valueOr('Guest'))
* .then(name => displayUserName(name));
*/
Maybe.fromObservable = function (observable) {
return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('rxjs')); }).then(function (_a) {
var firstValueFrom = _a.firstValueFrom, EMPTY = _a.EMPTY, take = _a.take, map = _a.map, catchError = _a.catchError;
return firstValueFrom(observable.pipe(take(1), map(function (value) { return new Maybe(value); }), catchError(function () { return EMPTY; }))).then(function (maybeValue) { return maybeValue; }, function () { return new Maybe(); });
});
};
/**
* Transforms an array of Maybe values into a Maybe containing an array of values.
*
* If all Maybes in the input array are Some, returns a Some containing an array of all values.
* If any Maybe in the input array is None, returns None.
*
* @param maybes An array of Maybe values
* @returns A Maybe containing an array of all values if all inputs are Some, otherwise None
*
* @example
* // All Maybes are Some
* const result1 = Maybe.sequence([maybe(1), maybe(2), maybe(3)]);
* // result1 is Some([1, 2, 3])
*
* // One Maybe is None
* const result2 = Maybe.sequence([maybe(1), maybe(null), maybe(3)]);
* // result2 is None
*/
Maybe.sequence = function (maybes) {
var e_1, _a;
if (maybes.length === 0) {
return new Maybe([]);
}
var values = [];
try {
for (var maybes_1 = __values(maybes), maybes_1_1 = maybes_1.next(); !maybes_1_1.done; maybes_1_1 = maybes_1.next()) {
var m = maybes_1_1.value;
if (m.isNone()) {
return new Maybe();
}
values.push(m.valueOrThrow());
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (maybes_1_1 && !maybes_1_1.done && (_a = maybes_1.return)) _a.call(maybes_1);
}
finally { if (e_1) throw e_1.error; }
}
return new Maybe(values);
};
Maybe.prototype.isSome = function () {
return !this.isNone();
};
Maybe.prototype.isNone = function () {
return this.value === null || this.value === undefined;
};
Maybe.prototype.valueOr = function (value) {
return this.isSome() ? this.value : value;
};
Maybe.prototype.valueOrUndefined = function () {
return this.isSome() ? this.value : undefined;
};
Maybe.prototype.valueOrNull = function () {
return this.isSome() ? this.value : null;
};
Maybe.prototype.valueOrCompute = function (fn) {
return this.isSome() ? this.value : fn();
};
Maybe.prototype.valueOrThrow = function (msg) {
return this.isNone() ? (function () { throw new Error(msg); })() : this.value;
};
Maybe.prototype.valueOrThrowErr = function (err) {
return this.isNone()
? (function () { return err instanceof Error ? (function () { throw err; })() : (function () { throw new Error(); })(); })()
: this.value;
};
Maybe.prototype.tap = function (obj) {
this.isNone()
? typeof obj.none === 'function' && obj.none()
: typeof obj.some === 'function' && obj.some(this.value);
};
Maybe.prototype.tapNone = function (fn) {
(this.isNone()) && fn();
};
Maybe.prototype.tapSome = function (fn) {
(this.isSome()) && fn(this.value);
};
Maybe.prototype.tapThru = function (val) {
this.tap(val);
return this;
};
Maybe.prototype.tapThruNone = function (fn) {
this.tapNone(fn);
return this;
};
Maybe.prototype.tapThruSome = function (fn) {
this.tapSome(fn);
return this;
};
Maybe.prototype.match = function (pattern) {
return this.isNone()
? pattern.none()
: pattern.some(this.value);
};
Maybe.prototype.toArray = function () {
return this.isNone()
? []
: Array.isArray(this.value)
? this.value
: [this.value];
};
Maybe.prototype.map = function (fn) {
return this.isSome()
? new Maybe(fn(this.value))
: new Maybe();
};
Maybe.prototype.mapTo = function (t) {
return this.isSome()
? new Maybe(t)
: new Maybe();
};
Maybe.prototype.flatMap = function (fn) {
return this.isNone() ?