UNPKG

option-t

Version:

A toolkit of Nullable/Option/Result type implementation in ECMAScript. Their APIs are inspired by Rust's `Option<T>` and `Result<T, E>`.

256 lines (255 loc) 7.59 kB
/** * @deprecated * See https://github.com/option-t/option-t/issues/459 * * The base object of `Some<T>` and `None<T>`. * * XXX: * In general case, __we must not use this base object__. * __Use `Option<T>` interface strongly__. * * You can only this object if you need to cooperate with some libralies * like `React.PropTypes` which are use `instanceof` checking to work together with * others in the pure JavaScript world. * * The typical case is TSX (TypeScript JSX) syntax. * https://github.com/Microsoft/TypeScript/wiki/JSX * * Our basic stance is that _you don't use this and need not it in almost case_. * * See also: * https://github.com/option-t/option-t/pull/77 */ export class ClassicOptionBase { constructor(ok, val) { this.ok = ok; this.val = val; Object.seal(this); } /** * Return whether this is `Some<T>` or not. */ get isSome() { return this.ok; } /** * Return whether this is `None` or not. */ get isNone() { return !this.ok; } /** * Returns the inner `T` of a `Some<T>`. * @throws {TypeError} * Throws if the self value equals `None`. */ unwrap() { if (!this.ok) { throw new TypeError('called `unwrap()` on a `None` value'); } // This code is required to keep backward compatibility. // @ts-expect-error return this.val; } /** * Returns the contained value or a default value `def`. */ unwrapOr(def) { // This code is required to keep backward compatibility. // @ts-expect-error return this.ok ? this.val : def; } /** * Returns the contained value or computes it from a closure `fn`. */ unwrapOrElse(fn) { // This code is required to keep backward compatibility. // @ts-expect-error return this.ok ? this.val : fn(); } /** * Returns the inner `T` of a `Some<T>`. * @throws {TypeError} * Throws a custom error with provided `msg` * if the self value equals `None`. */ expect(msg) { if (!this.ok) { throw new TypeError(msg); } // This code is required to keep backward compatibility. // @ts-expect-error return this.val; } /** * Maps an `Option<T>` to `Option<U>` by applying a function to a contained value. */ map(fn) { if (!this.ok) { // cheat to escape from a needless allocation. // @ts-expect-error return this; } // This code is required to keep backward compatibility. // @ts-expect-error const value = fn(this.val); const option = createClassicSome(value); return option; } /** * Returns `None` if the self is `None`, * otherwise calls `fn` with the wrapped value and returns the result. */ flatMap(fn) { if (!this.ok) { // cheat to escape from a needless allocation. // @ts-expect-error return this; } // This code is required to keep backward compatibility. // @ts-expect-error const mapped = fn(this.val); const isOption = mapped instanceof ClassicOptionBase; if (!isOption) { throw new TypeError("Option<T>.flatMap()' param `fn` should return `Option<T>`."); } return mapped; } /** * Applies a function `fn` to the contained value or returns a default `def`. */ mapOr(def, fn) { if (this.ok) { // This code is required to keep backward compatibility. // @ts-expect-error return fn(this.val); } else { return def; } } /** * Applies a function `fn` to the contained value or computes a default result by `defFn`. */ mapOrElse(def, fn) { if (this.ok) { // This code is required to keep backward compatibility. // @ts-expect-error return fn(this.val); } else { return def(); } } /** * Returns `None` if the self is `None`, otherwise returns `optb`. */ and(optb) { // This code is required to keep backward compatibility. // @ts-expect-error return this.ok ? optb : this; } /** * The alias of `Option<T>.flatMap()`. */ andThen(fn) { return this.flatMap(fn); } /** * Returns the self if it contains a value, otherwise returns `optb`. * * @template T * * @param {!Option<T>} optb * @return {!Option<T>} */ or(optb) { // This code is required to keep backward compatibility. // @ts-expect-error return this.ok ? this : optb; } /** * Returns the self if it contains a value, * otherwise calls `fn` and returns the result. */ orElse(fn) { if (this.ok) { // This code is required to keep backward compatibility. // @ts-expect-error return this; } else { const value = fn(); if (value instanceof ClassicOptionBase) { return value; } throw new TypeError("Option<T>.orElse()' param `fn` should return `Option<T>`."); } } /** * Finalize the self. * After this is called, the object's behavior is not defined. * * @param destructor * This would be called with the inner value if self is `Some<T>`. */ drop(destructor) { if (this.ok && typeof destructor === 'function') { // This code is required to keep backward compatibility. // @ts-expect-error destructor(this.val); } // This code is required to keep backward compatibility. // @ts-expect-error this.val = null; Object.freeze(this); } // FYI: this is json representation. // eslint-disable-next-line @typescript-eslint/naming-convention toJSON() { return { // eslint-disable-next-line @typescript-eslint/naming-convention is_some: this.ok, value: this.val, }; } } Object.freeze(ClassicOptionBase.prototype); /** * @deprecated * See https://github.com/option-t/option-t/issues/459 */ export function createClassicSome(val) { // This code is required to keep backward compatibility. // @ts-expect-error const o = new ClassicOptionBase(true, val); return o; } /** * @deprecated * See https://github.com/option-t/option-t/issues/459 */ export function createClassicNone() { // This code is required to keep backward compatibility. // @ts-expect-error const o = new ClassicOptionBase(false, undefined); return o; } /** * @deprecated * See https://github.com/option-t/option-t/issues/459 */ // eslint-disable-next-line @typescript-eslint/naming-convention export const ClassicSomeConstructor = function ClassicSomeConstructor(val) { return createClassicSome(val); // eslint-disable-next-line @typescript-eslint/no-explicit-any }; /** * @deprecated * See https://github.com/option-t/option-t/issues/459 */ // eslint-disable-next-line @typescript-eslint/naming-convention export const ClassicNoneConstructor = function ClassicNoneConstructor() { return createClassicNone(); // eslint-disable-next-line @typescript-eslint/no-explicit-any };