Skip to content

Instantly share code, notes, and snippets.

@todokr
Created July 9, 2022 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save todokr/46dddfef14e622d49a3d474855e5041d to your computer and use it in GitHub Desktop.
Save todokr/46dddfef14e622d49a3d474855e5041d to your computer and use it in GitHub Desktop.
An util for Railway Oriented Programming
/** An util for Railway Oriented Programming
*
* @example
* import { pipe } from "./pipe.ts";
*
* const DB = {
* write: (_: unknown) => {},
* };
*
* const validate = (input: unknown): Result<number, "NOT_AN_INTEGER"> => {
* if (Number.isInteger(input)) {
* return Result.failed("NOT_AN_INTEGER");
* } else {
* return Result.successful(input as number);
* }
* };
*
* const updateDB = (input: number): Result<Date, "DB_UNAVAILABLE"> => {
* try {
* DB.write(input);
* return Result.successful(new Date());
* } catch (_) {
* return Result.failed("DB_UNAVAILABLE");
* }
* };
*
* const log = (value: unknown) => console.log("[RP]:", value);
*
* // Result<Date, "NOT_AN_INTEGER" | "DB_UNAVAILABLE">
* const action = (input: unknown) =>
* pipe(
* input,
* validate,
* chain(updateDB),
* tee(log),
* );
*/
export type Success<T> = { readonly type: "success"; value: T };
export type Failure<E> = { readonly type: "failure"; error: E };
export type Result<T, E> = Success<T> | Failure<E>;
export const Result = {
successful: <T>(value: T): Success<T> => ({ type: "success", value }),
failed: <E>(error: E): Failure<E> => ({ type: "failure", error }),
};
const chain = <T, S, E>(f: (a: T) => Result<S, E>) =>
<F>(r: Result<T, F>): Result<S, E | F> =>
r.type === "success" ? f(r.value) : r;
const tee = <T, E>(f: (a: unknown) => void) =>
(r: Result<T, E>): Result<T, E> => {
if (r.type === "success") {
f(r.value);
}
return r;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment