perlica
Version:
> [!WARNING] > 🚧 Work in progress!
268 lines (218 loc) • 8.1 kB
text/typescript
/* 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>;
}
});
});