UNPKG

perlica

Version:

> [!WARNING] > 🚧 Work in progress!

268 lines (218 loc) • 8.1 kB
/* eslint-disable @stylistic/yield-star-spacing */ import { describe, it, expect } from "bun:test"; import { err, ok, type Err, type Ok, type Result, bind } from "~/Result"; import type { Assert } from "./Helpers"; describe("result", () => { const resultOk = ok(1) as Result<number, string>; const resultErr = err(1) as Result<string, number>; const unionOk = ok(1) as Ok<number> | Err<string>; const unionErr = err(1) as Ok<string> | Err<number>; it("map", () => { { const a = ok(1).map(x => "hi" + x); const b = err(1).map(_x => "foo"); expect(a).toEqual(ok("hi1")); expect(b).toEqual(err(1)); type _a = Assert<Result<string, never>, typeof a>; type _b = Assert<Result<string, number>, typeof b>; } { const a = resultOk.map(x => x + 1); const b = resultErr.map(_x => "foo"); expect(a).toEqual(ok(2)); expect(b).toEqual(err(1)); type _a = Assert<Result<number, string>, typeof a>; type _b = Assert<Result<string, number>, typeof b>; } { const a = unionOk.map(x => x + 1); const b = unionErr.map(_x => "foo"); expect(a).toEqual(ok(2)); expect(b).toEqual(err(1)); type _a = Assert<Result<number, string>, typeof a>; type _b = Assert<Result<string, number>, typeof b>; } }); it("mapErr", () => { { const a = ok(1).mapErr(x => x + 1); const b = err(1).mapErr(x => `foo ${x}`); expect(a).toEqual(ok(1)); expect(b).toEqual(err("foo 1")); type _a = Assert<Result<number, number>, typeof a>; type _b = Assert<Result<never, string>, typeof b>; } { const a = resultOk.mapErr(_ => 1); const b = resultErr.mapErr(x => `foo ${x}`); expect(a).toEqual(ok(1)); expect(b).toEqual(err("foo 1")); type _a = Assert<Result<number, number>, typeof a>; type _b = Assert<Result<string, string>, typeof b>; } { const a = unionOk.mapErr(_ => 1); const b = unionErr.mapErr(x => `foo ${x}`); expect(a).toEqual(ok(1)); expect(b).toEqual(err("foo 1")); type _a = Assert<Result<number, number>, typeof a>; type _b = Assert<Result<string, string>, typeof b>; } }); it("andThen", () => { { const a = ok(1).andThen(x => ok(`hi ${x}`)); const b = ok(1).andThen(x => err(x + 4)); const c = err(1).andThen(x => ok(`hi ${x}`)); const d = err(1).andThen(_ => err(4)); expect(a).toEqual(ok("hi 1")); expect(b).toEqual(err(5)); expect(c).toEqual(err(1)); expect(d).toEqual(err(1)); type _a = Assert<Result<string, never>, typeof a>; type _b = Assert<Result<never, number>, typeof b>; type _c = Assert<Result<string, number>, typeof c>; type _d = Assert<Result<never, number>, typeof d>; } { const a = resultOk.andThen(x => ok(`hi ${x}`)); const b = resultOk.andThen(x => err("hi" + x)); const c = resultErr.andThen(x => ok(`hi ${x}`)); const d = resultErr.andThen(_ => err(4)); expect(a).toEqual(ok("hi 1")); expect(b).toEqual(err("hi1")); expect(c).toEqual(err(1)); expect(d).toEqual(err(1)); type _a = Assert<Result<string, string>, typeof a>; type _b = Assert<Result<never, string>, typeof b>; type _c = Assert<Result<string, number>, typeof c>; type _d = Assert<Result<never, number>, typeof d>; } { const a = unionOk.andThen(x => ok(`hi ${x}`)); const b = unionOk.andThen(x => err("hi" + x)); const c = unionErr.andThen(x => ok(`hi ${x}`)); const d = unionErr.andThen(_ => err(4)); expect(a).toEqual(ok("hi 1")); expect(b).toEqual(err("hi1")); expect(c).toEqual(err(1)); expect(d).toEqual(err(1)); type _a = Assert<Result<string, string>, typeof a>; type _b = Assert<Result<never, string>, typeof b>; type _c = Assert<Result<string, number>, typeof c>; type _d = Assert<Result<never, number>, typeof d>; } }); it("orElse", () => { { const a = ok(1).orElse(_ => ok(4)); const b = ok(1).orElse(_ => err(4)); const c = err(1).orElse(x => ok(`hi ${x}`)); const d = err(1).orElse(_ => err(4)); expect(a).toEqual(ok(1)); expect(b).toEqual(ok(1)); expect(c).toEqual(ok("hi 1")); expect(d).toEqual(err(4)); type _a = Assert<Result<number, never>, typeof a>; type _b = Assert<Result<number, number>, typeof b>; type _c = Assert<Result<string, never>, typeof c>; type _d = Assert<Result<never, number>, typeof d>; } { const a = resultOk.orElse(_ => ok(4)); const b = resultOk.orElse(_ => err(4)); const c = resultErr.orElse(x => ok(`hi ${x}`)); const d = resultErr.orElse(_ => err(4)); expect(a).toEqual(ok(1)); expect(b).toEqual(ok(1)); expect(c).toEqual(ok("hi 1")); expect(d).toEqual(err(4)); type _a = Assert<Result<number, never>, typeof a>; type _b = Assert<Result<number, number>, typeof b>; type _c = Assert<Result<string, never>, typeof c>; type _d = Assert<Result<string, number>, typeof d>; } { const a = unionOk.orElse(_ => ok(4)); const b = unionOk.orElse(_ => err(4)); const c = unionErr.orElse(x => ok(`hi ${x}`)); const d = unionErr.orElse(_ => err(4)); expect(a).toEqual(ok(1)); expect(b).toEqual(ok(1)); expect(c).toEqual(ok("hi 1")); expect(d).toEqual(err(4)); type _a = Assert<Result<number, never>, typeof a>; type _b = Assert<Result<number, number>, typeof b>; type _c = Assert<Result<string, never>, typeof c>; type _d = Assert<Result<string, number>, typeof d>; } }); it("unwrap", () => { { const a = ok(1).unwrap(); const b = () => err(1).unwrap(); expect(a).toEqual(1); expect(b).toThrow(`called \`Result.unwrap()\` on an \`Err\` value: 1`); type _a = Assert<number, typeof a>; type _b = Assert<() => never, typeof b>; } { const a = resultOk.unwrap(); const b = () => resultErr.unwrap(); expect(a).toEqual(1); expect(b).toThrow(`called \`Result.unwrap()\` on an \`Err\` value: 1`); type _a = Assert<number, typeof a>; type _b = Assert<() => string, typeof b>; } { const a = unionOk.unwrap(); const b = () => unionErr.unwrap(); expect(a).toEqual(1); expect(b).toThrow(`called \`Result.unwrap()\` on an \`Err\` value: 1`); type _a = Assert<number, typeof a>; type _b = Assert<() => string, typeof b>; } }); it("bind", () => { { const a = bind(function* () { return yield* ok(1); }).unwrap(); const b = () => bind(function* () { return yield* err(1); }).unwrap(); expect(a).toEqual(1); expect(b).toThrow(`called \`Result.unwrap()\` on an \`Err\` value: 1`); type _a = Assert<number, typeof a>; type _b = Assert<() => never, typeof b>; } { const a = bind(function* () { const a = yield* ok(1); const b = yield* ok({ num: 1 }); return a + b.num; }).unwrap(); expect(a).toEqual(2); type _a = Assert<number, typeof a>; } { const a = bind(function* () { const a = yield* ok(1); const b = yield* err("error"); return a + b; }); expect(a.value).toEqual("error"); type _a = Assert<Result<number, string>, typeof a>; } { const a = bind(function* () { const a = yield* ok(1); const b = yield* err("error"); const c = yield* err(22); return a + b + c; }); expect(a.value).toEqual("error"); type _a = Assert<Result<number, string | number>, typeof a>; } }); });