/** * represents a simple "present or absent" type. * * This is very similar to existing implementations, e.g. in fp-ts * and differs mostly in that the types are a bit more relaxed. * * @module */ import { identity } from "./Function.js"; export type Option = Readonly< { __tag: "some"; value: T } | { __tag: "none" } >; export const some = (value: T): Option => ({ __tag: "some", value }); export const none: Option = { __tag: "none" }; export const fromNullable = (value: T | undefined | null): Option => value == null ? none : some(value); export const map = (fn: (value: T) => U) => (option: Option): Option => option.__tag === "none" ? option : some(fn(option.value)); export const flatMap = (fn: (value: T) => Option) => (option: Option): Option => option.__tag === "none" ? option : fn(option.value); export const match = (onNone: () => R, onSome: (value: T) => R) => (option: Option): R => option.__tag === "none" ? onNone() : onSome(option.value); export const getOrElse = (fn: () => F) => match(fn, identity); export const toUndefined = (option: Option): T | undefined => getOrElse(() => undefined)(option); export const alt = (second: Option) => (first: Option) => first.__tag === "some" ? first : second; /** * attempt to evaluate a function, returns none if evaluation throws */ export const attempt = (fn: () => T): Option => { try { return some(fn()); } catch { return none; } };