/// import * as _ from 'lodash'; export interface Option { get(): T; isEmpty(): Boolean; isDefined(): Boolean; contains(value: T): Boolean; exists(predicate: (value: T) => Boolean): Boolean; filter(predicate: (value: T) => Boolean): Option; flatMap(transformer: (value: T) => Option): Option; map(transformer: (value: T) => U): Option; flatten(): Option; getOrElse(other: T): T; orNull(): T; match(matcher: { some: (val: T) => U, none: () => U }): U; } export class Some implements Option { value: T; constructor(val: T) { this.value = val; } get(): T { return this.value; } isEmpty(): Boolean { return false; } isDefined(): Boolean { return true; } contains(value: T): Boolean { return _.isEqual(this.value, value); } exists(predicate: (value: T) => Boolean): Boolean { return predicate(this.value); } filter(predicate: (value: T) => Boolean): Option { if (predicate(this.value)) { return this; } else { return new None(); } } flatMap(transformer: (value: T) => Option): Option { return transformer(this.value); } map(transformer: (value: T) => U): Option { return new Some(transformer(this.value)); } flatten(): Option { if (!!this.value['flatten']) { let innerOpt = > this.value; return > innerOpt.flatten(); } else { return new Some(this.value); } } getOrElse(other: T): T { return this.value; } orNull(): T { return this.value; } match(matcher: { some: ((val: T) => U), none: (() => U) }): U { return matcher.some(this.value); } } export class None implements Option { get(): T { return undefined; } isEmpty(): Boolean { return true; } isDefined(): Boolean { return false; } contains(value: T): Boolean { return false; } exists(predicate: (value: T) => Boolean): Boolean { return false; } filter(predicate: (value: T) => Boolean): Option { return new None(); } flatMap(transformer: (value: T) => Option): Option { return new None(); } flatten(): Option { return new None(); } map(transformer: (value: T) => U): Option { return new None(); } getOrElse(other: T): T { return other; } orNull(): T { return null; } match(matcher: { some: ((val: T) => U), none: (() => U) }): U { return matcher.none(); } }