@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
JavaScript
'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;