import { unknown } from "../.." ; import { Either , Left , Right } from "./either" ; import { UnitLike } from "./unit" ; declare const OptionId = "typeprops/lib/data/option" ; declare module "typeprops" { interface TypeProps < T , Params > { [ OptionId ] : { infer : T extends Option < infer L > ? [ L ] : never ; construct : Option < Params [ 0 ] > ; } ; } } export type Nullable < T = unknown > = T | null | undefined ; export type None = Option < never > ; export class Option < T > { static nothing : None = new Option ( undefined as never ) ; static from < V > ( iterable ) { if ( iterable == undefined ) { return Option . nothing ; } let iterator = ( iterable as any ) [ Symbol . iterator ] ; if ( typeof iterator === "function" || iterator . toString ( ) === "[object Function]" ) { let next = iterator . next ( ) ; return new Option ( next . value ) ; } let value = iterable as any ; if ( "length" in value && 0 in value ) { return new Option ( value [ 0 ] ) ; } if ( "value" in value ) { return new Option ( value . value ) ; } return new Option ( value ) ; } static isOption < T > ( maybe ) ; static isOption ( maybe ) { return maybe instanceof Option ; } value : Nullable < T > ; constructor ( value ) { this . value = value ; if ( value == undefined ) { return Option . nothing ; } } isNothing ( ) { return this . value == undefined ; } map < U > ( transform ) { return this . value == undefined ? Option . nothing : new Option ( transform ( this . value ) ) ; } chain < U > ( transform ) { return this . value == undefined ? Option . nothing : transform ( this . value ) ; } toEither < E > ( left ) { return this . value == undefined ? new Left ( left ) : new Right ( this . value ) ; } * [ Symbol . iterator ] ( ) { if ( this . value != undefined ) yield this . value ; } } export class Some < T extends { } > extends Option < T > { constructor ( a ) { if ( a == undefined ) throw new TypeError ( `argument is null or undefined` ) ; super ( a ) ; } } export namespace Option { export const zero = ( ) : None => Option . nothing ; export const of = < T > ( a ) : Option < T > => new Option ( a ) ; export const isNothing = < T > ( maybe ) : maybe is None => maybe . isNothing ( ) ; export const map = < T , U > ( transform , maybe ) : Option < U > => maybe . map ( transform ) ; export const chain = < T , U > ( transform , maybe ) : Option < U > => maybe . chain ( transform ) ; }