UNPKG

@jumpaku/async-result

Version:

A typescript library that provides Result, Option, and AsyncResult.

150 lines (143 loc) 3.52 kB
interface IOption<T> extends ArrayLike<T>, Iterable<T> { isSome(): this is Some<T>; isNone(): this is None<T>; map<U>(f: (value: T) => U): Option<U>; flatMap<U>(f: (value: T) => Option<U>): Option<U>; orDefault(value: T): T; orBuild(f: () => T): T; orThrow<E>(f?: () => E): T; orNull(): T | null; orUndefined(): T | undefined; takeIf(f: (value: T) => boolean): Option<T>; takeIfNotNull(): Option<NonNullable<T>>; ifPresent(f: (value: T) => void): Option<T>; ifAbsent(f: () => void): Option<T>; and<U>(other: Option<U>): Option<T | U>; or<U>(other: Option<U>): Option<T | U>; readonly length: 0 | 1; [index: number]: T; [Symbol.iterator]: () => Iterator<T>; } class Some<T> implements IOption<T> { constructor(readonly value: T) {} isSome(): this is Some<T> { return true; } isNone(): this is None<T> { return false; } flatMap<U>(f: (value: T) => Option<U>): Option<U> { return f(this.value); } map<U>(f: (value: T) => U): Option<U> { return new Some(f(this.value)); } orDefault(value: T): T { return this.value; } orBuild(f: () => T): T { return this.value; } orThrow<E>(f?: () => E): T { return this.value; } orNull(): T | null { return this.value; } orUndefined(): T | undefined { return this.value; } takeIf(f: (value: T) => boolean): Option<T> { return f(this.value) ? this : none(); } takeIfNotNull(): Option<NonNullable<T>> { return nonNull(this.value); } ifPresent(f: (value: T) => void): Option<T> { f(this.value); return this; } ifAbsent(f: () => void): Option<T> { return this; } and<U>(other: Option<U>): Option<T | U> { return other; } or<U>(other: Option<U>): Option<T | U> { return this; } readonly length = 1; [index: number]: T; 0 = this.value; [Symbol.iterator] = (): Iterator<T> => { const value = this.value; return (function* () { yield value; })(); }; } class None<T = never> implements IOption<T> { static readonly instance = new None(); private constructor() {} isSome(): this is Some<T> { return false; } isNone(): this is None<T> { return true; } flatMap<U>(f: (value: T) => Option<U>): Option<U> { return None.instance; } map<U>(f: (value: T) => U): Option<U> { return None.instance; } orDefault(value: T): T { return value; } orBuild(f: () => T): T { return f(); } orThrow<E>(f?: () => E): T { throw f != null ? f() : new Error("Option is None."); } orNull(): T | null { return null; } orUndefined(): T | undefined { return undefined; } takeIf(f: (value: T) => boolean): Option<T> { return this; } takeIfNotNull(): Option<NonNullable<T>> { return None.instance; } ifPresent(f: (value: T) => void): Option<T> { return this; } ifAbsent(f: () => void): Option<T> { f(); return this; } and<U>(other: Option<U>): Option<T | U> { return this; } or<U>(other: Option<U>): Option<T | U> { return other; } readonly length = 0; [index: number]: T; [Symbol.iterator] = (): Iterator<T> => (function* () {})(); } export type Option<T> = Some<T> | None<T>; export function none<T = never>(): Option<T> { return None.instance; } export function some<T>(value: T): Option<T> { return new Some<T>(value); } export function nonNull<T>(nullable: T): Option<NonNullable<T>> { return ((a: T): a is NonNullable<T> => a != null)(nullable) ? some(nullable) : none(); }