Last active
June 13, 2022 08:51
-
-
Save robinpokorny/fbbff6908dd54072831694ebea3de3c1 to your computer and use it in GitHub Desktop.
Revisions
-
robinpokorny revised this gist
Jun 13, 2022 . 1 changed file with 18 additions and 10 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -33,7 +33,7 @@ const g = (a: Person | Pet) => { } }; /* === 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) ); if (response.tag === "failure") { switch (response.value) { case "DB_UNAVAILABLE": @@ -140,7 +141,13 @@ const action = (input: unknown) => { }; // A: `string`-`number` mismatch // 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] -
robinpokorny created this gist
Jun 11, 2022 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal 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";