UNPKG

@rustable/enum

Version:

Rust-inspired pattern matching and type-safe error handling for TypeScript. Includes Option<T> for null-safety and Result<T, E> for error handling, with comprehensive pattern matching support

352 lines (348 loc) 8.67 kB
'use strict'; var _enum = require('./enum.js'); "use strict"; class Option extends _enum.Enum { static { this.NI = new Option("None"); } /** * Creates a Some variant containing a value. * * @template T The type of value to wrap * @param val The value to wrap * @returns Option<T> containing the value * * @example * ```typescript * const num = Some(42); // Option<number> * const str = Some("hello"); // Option<string> * const obj = Some({x: 1}); // Option<{x: number}> * ``` */ static Some(value) { return new Option("Some", value); } /** * Creates an Option containing no value * @returns Option containing no value * * @example * ```typescript * const empty = None; * ``` */ static None() { return Option.NI; } /** * Pattern matches on the Option, executing different code paths for Some and None cases. * Similar to Rust's enum expression. * * @param fn Object containing functions for Some and None cases * @returns Result of the matched function * * @example * ```typescript * const opt = Some(5); * const result = opt.enum({ * some: (val) => val * 2, * none: () => 0 * }); // result = 10 * ``` */ match(patterns) { return super.match(patterns); } /** * Checks if the Option contains a value (Some variant) * @returns true if Some, false if None * * @example * ```typescript * const opt = Some(5); * if (opt.isSome()) { * console.log("Has value"); * } * ``` */ isSome() { return this.is("Some"); } /** * Tests if Option is Some and the value matches a predicate * @param fn Predicate function to test the contained value * @returns true if Some and predicate returns true * * @example * ```typescript * const opt = Some(5); * if (opt.isSomeAnd(n => n > 0)) { * console.log("Has positive value"); * } * ``` */ isSomeAnd(fn) { return this.isSome() ? fn(super.unwrap()) : false; } /** * Checks if the Option is None variant * @returns true if None, false if Some * * @example * ```typescript * const empty = None; * if (empty.isNone()) { * console.log("Is empty"); * } * ``` */ isNone() { return !this.isSome(); } /** * Tests if Option is None or the value matches a predicate * @param fn Predicate function to test the contained value * @returns true if None or predicate returns true * * @example * ```typescript * const empty = None; * if (empty.isNoneOr(n => n > 0)) { * console.log("Is empty or has positive value"); * } * ``` */ isNoneOr(fn) { return this.isSome() ? fn(super.unwrap()) : true; } /** * Returns the contained value or throws if None * @throws {Error} If the Option is None * @returns The contained value * * @example * ```typescript * const opt = Some(5); * const result = opt.expect("Expected Some value"); // 5 * ``` */ expect(msg) { if (this.isSome()) return super.unwrap(); throw new Error(msg); } /** * Returns the contained value or throws if None * @throws {ReferenceError} If the Option is None * @returns The contained value * * @example * ```typescript * const opt = Some(5); * const result = opt.unwrap(); // 5 * ``` */ unwrap() { if (this.isSome()) return super.unwrap(); throw new ReferenceError("Called unwrap on a None value"); } /** * Returns the contained value or a default * @param def Default value to return if None * @returns Contained value if Some, default if None * * @example * ```typescript * const empty = None; * const result = empty.unwrapOr(0); // 0 * ``` */ unwrapOr(def) { return this.isSome() ? super.unwrap() : def; } /** * Returns the contained value or computes a default * @param fn Function to compute default value if None * @returns Contained value if Some, computed default if None * * @example * ```typescript * const empty = None; * const result = empty.unwrapOrElse(() => 0); // 0 * ``` */ unwrapOrElse(fn) { return this.isSome() ? super.unwrap() : fn(); } /** * Transforms the Option's contained value using a mapping function * @param fn Function to transform the contained value * @returns New Option containing the transformed value * * @example * ```typescript * const opt = Some(5); * const mapped = opt.map(n => n.toString()); // Some("5") * ``` */ map(fn) { return this.isSome() ? Option.Some(fn(super.unwrap())) : Option.NI; } /** * Calls a function with the contained value if Some * @param fn Function to call with the contained value * @returns This Option * * @example * ```typescript * const opt = Some(5); * opt.inspect(n => console.log(n)); // 5 * ``` */ inspect(fn) { if (this.isSome()) fn(super.unwrap()); return this; } /** * Maps the contained value or returns a default if None * @param def Default value to use if None * @param fn Function to transform the contained value * @returns Transformed value or default * * @example * ```typescript * const opt = Some(5); * const result = opt.mapOr(0, n => n * 2); // 10 * ``` */ mapOr(def, fn) { return this.isSome() ? fn(super.unwrap()) : def; } /** * Maps the contained value or computes a default if None * @param def Function to compute default value if None * @param fn Function to transform the contained value * @returns Transformed value or computed default * * @example * ```typescript * const opt = Some(5); * const result = opt.mapOrElse(() => 0, n => n * 2); // 10 * ``` */ mapOrElse(def, fn) { return this.isSome() ? fn(super.unwrap()) : def(); } /** * Returns None if this is None, otherwise returns opt * @param opt Option to return if this is Some * @returns None if this is None, opt otherwise * * @example * ```typescript * const opt = Some(5); * const result = opt.and(Some(0)); // Some(0) * ``` */ and(opt) { return this.isSome() ? opt : Option.NI; } /** * Chains Option-returning functions * @param fn Function that returns an Option * @returns Result of fn if Some, None if this is None * * @example * ```typescript * const opt = Some(5); * const result = opt.andThen(n => Some(n * 2)); // Some(10) * ``` */ andThen(fn) { return this.isSome() ? fn(this.unwrap()) : Option.NI; } /** * Returns None if the predicate returns false, otherwise returns the Option * @param fn Predicate function to test the contained value * @returns This Option if predicate returns true, None otherwise * * @example * ```typescript * const opt = Some(5); * const result = opt.filter(n => n > 0); // Some(5) * ``` */ filter(fn) { return this.isSome() && fn(this.unwrap()) ? this : Option.NI; } /** * Returns this Option if Some, or the provided Option if None * @param opt Alternative Option to use if None * @returns This Option if Some, opt if None * * @example * ```typescript * const empty = None; * const result = empty.or(Some(0)); // Some(0) * ``` */ or(opt) { return this.isSome() ? this : opt; } /** * Returns this Option if Some, or computes a new Option if None * @param fn Function to compute new Option if None * @returns This Option if Some, result of fn if None * * @example * ```typescript * const empty = None; * const result = empty.orElse(() => Some(0)); // Some(0) * ``` */ orElse(fn) { return this.isSome() ? this : fn(); } /** * Returns the XOR of this Option and the provided Option * @param opt Option to XOR with * @returns XOR of this Option and opt * * @example * ```typescript * const opt1 = Some(5); * const opt2 = None; * const result = opt1.xor(opt2); // Some(5) * ``` */ xor(opt) { return this.match({ Some: () => opt.match({ Some: () => Option.None(), None: this }), None: () => opt.match({ Some: () => opt, None: Option.NI }) }); } toJSON() { return this.toString(); } toString() { return this.isSome() ? String(super.unwrap()) : null; } valueOf() { return this.isSome() ? super.unwrap()?.valueOf() : null; } } const None = Option.None(); function Some(val) { return Option.Some(val); } exports.None = None; exports.Option = Option; exports.Some = Some;