export interface Maybe { isJust(): this is Just; map(f: (x: T) => S): Maybe; getOrElse(x: T): T; } export type Just = Maybe & { get(): T }; export function just(value: T): Just { return { isJust: () => true, getOrElse: (_: T) => value, map: (f: (x: T) => S) => just(f(value)), get: () => value }; } export function nothing(): Maybe { return { isJust: () => false, getOrElse: (value: T) => value, map: (_: (x: T) => S) => nothing() }; } export function fromNullable(value: T): Maybe { return value == null ? nothing() : just(value); }