This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type Left<L> = { left: L }; | |
export type Right<R> = { right: R }; | |
export type Either<L, R> = Left<L> | Right<R>; | |
export function isLeft<L, R>(value: Either<L, R>): value is Left<L> { | |
return "left" in value; | |
} | |
export function isRight<L, R>(value: Either<L, R>): value is Right<R> { | |
return "right" in value; | |
} | |
export function Left<L>(left: L): Left<L> { | |
return { left }; | |
} | |
export function Right<R>(right: R): Right<R> { | |
return { right }; | |
} | |
export function fromLeft<L, R, DV>(value: Left<L>, defaultValue: DV): Left<L>; | |
export function fromLeft<L, R, DV>(value: Right<R>, defaultValue: DV): DV; | |
export function fromLeft<L, R, DV>(value: Either<L, R>, defaultValue: DV): Left<L> | DV; | |
export function fromLeft<L, R, DV>(value: Either<L, R>, defaultValue: DV) { | |
return isLeft(value) ? value.left : defaultValue; | |
} | |
export function fromRight<L, R, DV>(value: Right<R>, defaultValue: DV): Right<R>; | |
export function fromRight<L, R, DV>(value: Left<L>, defaultValue: DV): DV; | |
export function fromRight<L, R, DV>(value: Either<L, R>, defaultValue: DV): Right<R> | DV; | |
export function fromRight<L, R, DV>(value: Either<L, R>, defaultValue: DV) { | |
return isRight(value) ? value.right : defaultValue; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type Left<L> = { left: L }; | |
export type Right<R> = { right: R }; | |
export type Either<L, R> = Left<L> | Right<R>; | |
export function isLeft<L, R>(value: Either<L, R>): value is Left<L> { | |
return "left" in value; | |
} | |
export function isRight<L, R>(value: Either<L, R>): value is Right<R> { | |
return "right" in value; | |
} | |
export function Left<L>(left: L): Left<L> { | |
return { left }; | |
} | |
export function Right<R>(right: R): Right<R> { | |
return { right }; | |
} | |
export function fromLeft<L, R, DV>(value: Either<L, R>, defaultValue: DV) { | |
return isLeft(value) ? value.left : defaultValue; | |
} | |
export function fromRight<L, R, DV>(value: Either<L, R>, defaultValue: DV) { | |
return isRight(value) ? value.right : defaultValue; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type Left<L> = ["left", L]; | |
export type Right<R> = ["right", R]; | |
export type Either<L, R> = Left<L> | Right<R>; | |
export function isLeft<L, R>(value: Either<L, R>): value is Left<L> { | |
return value[0] === "left"; | |
} | |
export function isRight<L, R>(value: Either<L, R>): value is Right<R> { | |
return value[0] === "right"; | |
} | |
export function Left<L>(left: L): Left<L> { | |
return ["left", left]; | |
} | |
export function Right<R>(right: R): Right<R> { | |
return ["right", right]; | |
} | |
export function fromLeft<L, R, DV>(value: Either<L, R>, defaultValue: DV) { | |
return value[0] === "left" ? value[1] : defaultValue; | |
} | |
export function fromRight<L, R, DV>(value: Either<L, R>, defaultValue: DV) { | |
return value[0] === "right" ? value[1] : defaultValue; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Hackathon = { | |
name: string; | |
endDate: number; // UNIX epoch timestamp | |
startDate: number; | |
}; | |
type MyError = string; | |
type Predicate<N> = (val: N) => boolean; | |
function firstLeft<A, B>(val: B, predicatePairs: [Predicate<B>, A][]): Either<A, B> { | |
for (let i = 0; i < predicatePairs.length; i++) { | |
const [p, e] = predicatePairs[i]; | |
if (!p(val)) return Left(e); | |
} | |
return Right(val); | |
} | |
const StartDateMustBePositive = (h: Hackathon) => h.startDate > 0; | |
const EndDateMustBePositive = (h: Hackathon) => h.endDate > 0; | |
const HackathonSpec: [Predicate<Hackathon>, MyError][] = [ | |
[StartDateMustBePositive, "Start Date must be positive!"], | |
[EndDateMustBePositive, "End Date must be positive!"], | |
]; | |
function validateHackathon(h: Hackathon): Either<MyError, Hackathon> { | |
return firstLeft(h, HackathonSpec); | |
} | |
const x = validateHackathon({} as any); | |
if (isLeft(x)) { | |
const rUndefined = fromRight(x, undefined); | |
const rLeft = fromLeft(x, undefined); | |
const rValue = x.left; | |
} else { | |
const rRight = fromRight(x, undefined); | |
const rUndefined = fromLeft(x, undefined); | |
const rValue = x.right; | |
} | |
// unfortunatelly this doesn't work, in ideal world you would see type Either but instead it shows it as Either | undefined | |
const z = fromRight(x, fromLeft(x, undefined)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment