diff options
Diffstat (limited to 'u/types/fn/optional.ts')
-rw-r--r-- | u/types/fn/optional.ts | 93 |
1 files changed, 0 insertions, 93 deletions
diff --git a/u/types/fn/optional.ts b/u/types/fn/optional.ts deleted file mode 100644 index 504e496..0000000 --- a/u/types/fn/optional.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { type Mapper, Predicate, type Supplier, Tagged, isTagged } from '@emprespresso/pengueno'; - -export type MaybeGiven<T> = T | undefined | null; - -export const IOptionalTag = 'IOptional' as const; -export type IOptionalTag = typeof IOptionalTag; -export const isOptional = <T>(o: unknown): o is IOptional<T> => isTagged(o, IOptionalTag); -export class IOptionalEmptyError extends Error {} -export interface IOptional<t, T extends NonNullable<t> = NonNullable<t>> extends Tagged<IOptionalTag>, Iterable<T> { - readonly move: <_T>(t: MaybeGiven<_T>) => IOptional<_T>; - readonly map: <_T>(mapper: Mapper<T, MaybeGiven<_T>>) => IOptional<_T>; - readonly filter: (mapper: Predicate<T>) => IOptional<T>; - readonly flatMap: <_T>(mapper: Mapper<T, MaybeGiven<IOptional<_T>>>) => IOptional<_T>; - readonly orSome: (supplier: Supplier<MaybeGiven<t>>) => IOptional<T>; - readonly get: Supplier<T>; - readonly present: Supplier<boolean>; -} - -type OSomeTag = typeof OSomeTag; -const OSomeTag = 'O.Some' as const; -interface Some<T> extends Tagged<OSomeTag> { - value: NonNullable<T>; -} - -const ONoneTag = 'O.None' as const; -type ONoneTag = typeof ONoneTag; -interface None extends Tagged<ONoneTag> {} - -const isNone = (o: unknown): o is None => isTagged(o, ONoneTag); -const isSome = <T>(o: unknown): o is Some<T> => isTagged(o, OSomeTag); - -class _Tagged implements Tagged<IOptionalTag> { - protected constructor(public readonly _tag = IOptionalTag) {} -} - -export class Optional<t, T extends NonNullable<t> = NonNullable<t>> extends _Tagged implements IOptional<T> { - private constructor(private readonly self: Some<T> | None) { - super(); - } - - public move<_T>(t: MaybeGiven<_T>): IOptional<_T> { - return this.map(() => t); - } - - public orSome(supplier: Supplier<MaybeGiven<t>>): IOptional<T> { - if (isNone(this.self)) return Optional.from(supplier()); - return this; - } - - public get(): T { - if (isNone(this.self)) throw new IOptionalEmptyError('called get() on None optional'); - return this.self.value; - } - - public filter(mapper: Predicate<T>): IOptional<T> { - if (isNone(this.self) || !mapper(this.self.value)) return Optional.none(); - return Optional.some(this.self.value); - } - - public map<_T>(mapper: Mapper<T, MaybeGiven<_T>>): IOptional<_T> { - if (isNone(this.self)) return Optional.none(); - return Optional.from(mapper(this.self.value)) as IOptional<_T>; - } - - public flatMap<_T>(mapper: Mapper<T, MaybeGiven<IOptional<_T>>>): IOptional<_T> { - if (isNone(this.self)) return Optional.none(); - return Optional.from(mapper(this.self.value)) - .orSome(() => Optional.none()) - .get(); - } - - public present() { - return isSome(this.self); - } - - *[Symbol.iterator]() { - if (isSome(this.self)) yield this.self.value; - } - - static some<t, T extends NonNullable<t> = NonNullable<t>>(value: T): IOptional<T> { - return new Optional({ value, _tag: OSomeTag }); - } - - private static readonly _none = new Optional({ _tag: ONoneTag }); - static none<T>(): IOptional<T> { - return this._none as unknown as IOptional<T>; - } - - static from<t, T extends NonNullable<t> = NonNullable<t>>(value: MaybeGiven<t>): IOptional<T> { - if (value === null || value === undefined) return Optional.none<T>(); - return Optional.some(<T>value); - } -} |