Skip to content

Instantly share code, notes, and snippets.

@robinpokorny
Last active June 13, 2022 08:51
Show Gist options
  • Select an option

  • Save robinpokorny/fbbff6908dd54072831694ebea3de3c1 to your computer and use it in GitHub Desktop.

Select an option

Save robinpokorny/fbbff6908dd54072831694ebea3de3c1 to your computer and use it in GitHub Desktop.

Revisions

  1. robinpokorny revised this gist Jun 13, 2022. 1 changed file with 18 additions and 10 deletions.
    28 changes: 18 additions & 10 deletions index.ts
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@ const g = (a: Person | Pet) => {
    }
    };

    /* === 2. Result === */
    /* === 2. Success, Failure, Result === */

    type Success<T> = {
    tag: "success";
    @@ -98,6 +98,9 @@ const chain =
    return f(result.value);
    };

    // <F>(result: Result<number, F>) => Result<Date, "DB_UNAVAILABLE" | F>
    const chainedUpdateDB = chain(updateDB);

    const tee =
    <T, E>(f: (a: unknown) => void) =>
    (result: Result<T, E>): Result<T, E> => {
    @@ -107,22 +110,20 @@ const tee =
    return result;
    };

    // (result: Result<unknown, unknown>) => Result<unknown, unknown>
    const teedLog = tee(log);

    const action = (input: unknown) => {
    // pipe(a, b, c) == c(b(a))

    // Result<Date, "DB_UNAVAILABLE" | "NOT_AN_INTEGER">
    const response = pipe(
    input,
    validate,
    chain(updateDB),
    tee(log)
    );

    /*
    tee(log)(
    chain(updateDB)(
    validate(input)
    )
    )
    */

    if (response.tag === "failure") {
    switch (response.value) {
    case "DB_UNAVAILABLE":
    @@ -140,7 +141,13 @@ const action = (input: unknown) => {
    };

    // A: `string`-`number` mismatch
    // A: Forgot `chain`
    // B: Forgot `chain`







    // UTILS
    const DB = {
    @@ -149,3 +156,4 @@ const DB = {
    };
    export const input = 3;
    import { pipe } from "fp-ts/function";
    [a, b, c, code, action, f, g, chainedUpdateDB, teedLog]
  2. robinpokorny created this gist Jun 11, 2022.
    151 changes: 151 additions & 0 deletions index.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,151 @@
    /*
    =============================
    Railway Oriented Typescript
    =============================
    by @robinpokorny
    */

    /* === 1. Union basics === */

    const a: string | number = 42;

    const b: "hey" | "ahoy" = "hey";
    const c: "hey" | "ahoy" = "heyyyy"; // Error
    const code: 200 | 400 | 500 = 200;

    const f = (
    a: { name: string } | { age: number }
    ) => {
    a.name; // Property 'name' does not exist on type '{ name: string; } | { age: number; }'.

    if ("name" in a) {
    a.name;
    }
    };

    type Person = { tag: "person"; name: string };
    type Pet = { tag: "pet"; age: number };

    const g = (a: Person | Pet) => {
    if (a.tag === "person") {
    a.name;
    a.age; // Error
    }
    };

    /* === 2. Result === */

    type Success<T> = {
    tag: "success";
    value: T;
    };

    type Failure<E> = {
    tag: "failure";
    value: E;
    };

    type Result<T, E> = Success<T> | Failure<E>;

    /* === 3. Use Result === */

    const validate = (
    input: unknown
    ): Result<number, "NOT_AN_INTEGER"> => {
    if (Number.isInteger(input)) {
    return {
    tag: "success",
    value: input as number,
    };
    } else {
    return {
    tag: "failure",
    value: "NOT_AN_INTEGER",
    };
    }
    };

    const updateDB = (
    input: number
    ): Result<Date, "DB_UNAVAILABLE"> => {
    DB.write(input);

    if (DB.success) {
    return {
    tag: "success",
    value: new Date(),
    };
    } else {
    return {
    tag: "failure",
    value: "DB_UNAVAILABLE" as const,
    };
    }
    };

    const log = (value: unknown) =>
    console.log("[RP]:", value);

    /* === 4. Chain and Tee === */

    const chain =
    <T, S, E>(f: (a: T) => Result<S, E>) =>
    <F>(result: Result<T, F>): Result<S, E | F> => {
    if (result.tag === "failure") {
    return result;
    }

    return f(result.value);
    };

    const tee =
    <T, E>(f: (a: unknown) => void) =>
    (result: Result<T, E>): Result<T, E> => {
    if (result.tag === "success") {
    f(result.value);
    }
    return result;
    };

    const action = (input: unknown) => {
    const response = pipe(
    input,
    validate,
    chain(updateDB),
    tee(log)
    );

    /*
    tee(log)(
    chain(updateDB)(
    validate(input)
    )
    )
    */

    if (response.tag === "failure") {
    switch (response.value) {
    case "DB_UNAVAILABLE":
    return "…";
    case "NOT_AN_INTEGER":
    return "…";
    case "NOT_AN_ARRAY":
    return "…";
    }

    if (response) {
    // Unreachable code detected
    }
    }
    };

    // A: `string`-`number` mismatch
    // A: Forgot `chain`

    // UTILS
    const DB = {
    success: false,
    write: (x: unknown) => {},
    };
    export const input = 3;
    import { pipe } from "fp-ts/function";