-
-
Save adregan/1508255a5e84525958f9b4d80caffa39 to your computer and use it in GitHub Desktop.
Result
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
import { Result } from "./result"; | |
describe("Result", () => { | |
describe("creating", () => { | |
describe("Result.ok()", () => { | |
test("it returns an ok result", () => { | |
const result = Result.ok("I'm good"); | |
expect(result.isOk()).toBeTruthy(); | |
}); | |
test("an ok cannot be errored", () => { | |
const result = Result.ok("I'm not bad"); | |
expect(result.isErr()).toBeFalsy(); | |
}); | |
}); | |
describe("Result.err()", () => { | |
test("it returns an error result", () => { | |
const result = Result.err("I'm bad"); | |
expect(result.isErr()).toBeTruthy(); | |
}); | |
test("an error cannot be ok", () => { | |
const result = Result.err("I'm not good"); | |
expect(result.isOk()).toBeFalsy(); | |
}); | |
}); | |
}); | |
describe("result.match(onOk, onErr)", () => { | |
test("it can pattern match the ok value to the onOk op", () => { | |
const result: Result<string, Error> = Result.ok("hello"); | |
const actual = result.match( | |
(s: string) => `${s.toUpperCase()}!!`, | |
(_) => 2, | |
); | |
expect(actual).toEqual("HELLO!!"); | |
}); | |
test("it can pattern match the err value to the onErr op", () => { | |
const result: Result<string, Error> = Result.err(Error("KABOOM")); | |
expect( | |
result.match( | |
(_) => "I have a bad feeling about this.", | |
(e: Error) => `Something went ${e.message}`, | |
), | |
).toEqual("Something went KABOOM"); | |
}); | |
}); | |
describe("result.map(fn)", () => { | |
test("an ok value can be transformed via map", () => { | |
const result = Result.ok(2); | |
const value = result.map((x): string => `${x * 2}`); | |
expect(value).toEqual(4); | |
}); | |
test("an err value cannot be transformed via map", () => { | |
const result = Result.err(Error("OH NO")); | |
const value = result.map((x) => x * 3); | |
expect(value).toEqual(null); | |
}); | |
}); | |
}); |
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 class Result<Ok, Err = Error> { | |
#ok: Ok | null; | |
#err: Err | null; | |
private constructor({ ok, err }: { ok?: Ok; err?: Err }) { | |
this.#ok = ok ?? null; | |
this.#err = err ?? null; | |
} | |
static ok = <Ok>(ok: Ok): Result<Ok, never> => new Result({ ok }); | |
static err = <Err>(err: Err): Result<never, Err> => new Result({ err }); | |
isOk = (): this is Result<Ok, never> => this.#ok !== null; | |
isErr = (): this is Result<never, Err> => this.#err !== null; | |
match = <S, T>( | |
onOk: (ok: Ok) => S, | |
onErr: (err: Err) => T, | |
): this extends Result<Ok, never> ? S : T => | |
//@ts-ignore | |
this.isOk() ? onOk(this.#ok) : onErr(this.#err); | |
map = <B>(fn: (a: Ok) => B): Result<B, never> | this => | |
this.isOk() ? Result.ok(fn(this.#ok)) : this; | |
getOr = <V extends unknown>(value: V = null): Ok | V => (this.isOk() ? this.#ok : value); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment