export interface IEither { ok?: T; err?: E; mapBoth: ( errBranch: (e: E) => Ee, okBranch: (o: T) => Tt, ) => IEither; mapRight: (mapper: (t: T) => Tt) => Either; mapLeft: (mapper: (e: E) => Ee) => Either; flatMap: ( mapper: (e: T) => Either, ) => Either; } export class Either implements IEither { private constructor(readonly err?: E, readonly ok?: T) {} public mapBoth( errBranch: (e: E) => Ee, okBranch: (t: T) => Tt, ): Either { if (this.err) return Either.left(errBranch(this.err)); return Either.right(okBranch(this.ok!)); } public flatMap(mapper: (t: T) => Either) { if (this.ok) return mapper(this.ok); return this; } public mapRight(mapper: (t: T) => Tt): Either { if (this.ok) return Either.right(mapper(this.ok)); return Either.left(this.err!); } public mapLeft(mapper: (e: E) => Ee): Either { if (this.err) return Either.left(mapper(this.err)); return Either.right(this.ok!); } static left(e: E) { return new Either(e); } static right(t: T) { return new Either(undefined, t); } }