typescript-monads
Version:
Write cleaner TypeScript
333 lines • 12.8 kB
JavaScript
var __values = (this && this.__values) || function(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.");
};
var __read = (this && this.__read) || function (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;
};
var __spreadArray = (this && this.__spreadArray) || function (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));
};
import { FailResult, OkResult } from '../result/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 import('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() ? new Maybe() : fn(this.value);
};
Maybe.prototype.flatMapAuto = function (fn) {
return this.isNone()
? new Maybe()
: new Maybe(fn(this.value));
};
Maybe.prototype.project = function (fn) {
return this.flatMapAuto(fn);
};
Maybe.prototype.filter = function (fn) {
return this.isNone()
? new Maybe()
: fn(this.value)
? new Maybe(this.value)
: new Maybe();
};
Maybe.prototype.apply = function (maybeFn) {
return this.flatMap(function (v) { return maybeFn.flatMapAuto(function (f) { return f(v); }); });
};
Maybe.prototype.toResult = function (error) {
return this
.map(function (b) { return new OkResult(b); })
.valueOr(new FailResult(error));
};
Maybe.prototype.flatMapPromise = function (fn) {
if (this.isNone()) {
return Promise.resolve(new Maybe());
}
return fn(this.value)
.then(function (value) { return new Maybe(value); })
.catch(function () { return new Maybe(); });
};
Maybe.prototype.flatMapObservable = function (fn) {
var _this = this;
if (this.isNone()) {
return Promise.resolve(new Maybe());
}
return import('rxjs').then(function (_a) {
var firstValueFrom = _a.firstValueFrom, EMPTY = _a.EMPTY, take = _a.take, map = _a.map, catchError = _a.catchError;
return firstValueFrom(fn(_this.value).pipe(take(1), map(function (value) { return new Maybe(value); }), catchError(function () { return EMPTY; }))).then(function (maybeValue) { return maybeValue; }, function () { return new Maybe(); });
});
};
Maybe.prototype.flatMapMany = function (fn) {
if (this.isNone()) {
return Promise.resolve(new Maybe());
}
return Promise.all(fn(this.value))
.then(function (values) { return new Maybe(values); })
.catch(function () { return new Maybe(); });
};
Maybe.prototype.zipWith = function () {
var e_2, _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (this.isNone()) {
return new Maybe();
}
var fn = args[args.length - 1];
var maybes = args.slice(0, -1);
var values = [this.value];
try {
for (var maybes_2 = __values(maybes), maybes_2_1 = maybes_2.next(); !maybes_2_1.done; maybes_2_1 = maybes_2.next()) {
var m = maybes_2_1.value;
if (m.isNone()) {
return new Maybe();
}
values.push(m.valueOrThrow());
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (maybes_2_1 && !maybes_2_1.done && (_a = maybes_2.return)) _a.call(maybes_2);
}
finally { if (e_2) throw e_2.error; }
}
return new Maybe(fn.apply(void 0, __spreadArray([], __read(values), false)));
};
return Maybe;
}());
export { Maybe };
//# sourceMappingURL=maybe.js.map