import type { Mapper, Supplier } from "./mod.ts"; export interface IEither { mapBoth: ( errBranch: Mapper, okBranch: Mapper, ) => IEither; flatMap: (mapper: Mapper>) => IEither; mapRight: (mapper: Mapper) => IEither; mapLeft: (mapper: Mapper) => IEither; } export class Either implements IEither { private constructor(private readonly err?: E, private readonly ok?: T) {} public mapBoth( errBranch: Mapper, okBranch: Mapper, ): Either { if (this.err) return Either.left(errBranch(this.err)); return Either.right(okBranch(this.ok!)); } public flatMap(mapper: Mapper>) { if (this.ok) return mapper(this.ok); return Either.left(this.err!); } public mapRight(mapper: Mapper): IEither { if (this.ok) return Either.right(mapper(this.ok)); return Either.left(this.err!); } public mapLeft(mapper: Mapper) { 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); } static fromFailable(s: Supplier) { try { return Either.right(s()); } catch (e) { return Either.left(e as E); } } static async fromFailableAsync(s: Promise) { try { return Either.right(await s); } catch (e) { return Either.left(e as E); } } }