Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
MierenManz committed Jun 30, 2021
0 parents commit 282c17b
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vscode
./cov
43 changes: 43 additions & 0 deletions match.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Result } from "./result.ts";

interface MatchResult<Ok, Err, R> {
ok: (value: Ok) => R;
err: (value: Err) => R;
}

interface MatchPattern<V, R> {
[key: string]: (val: V) => R;
[key: number]: (val: V) => R;
_: (val: V) => R;
}

export function match<V extends string | number, R>(
value: V,
matchPattern: Partial<MatchPattern<V, R>>,
): R;

export function match<Ok, Err, R>(
res: Result<Ok, Err>,
match: MatchResult<Ok, Err, R>,
): R;

export function match<Ok, Err, R, V extends string | number>(
value: Result<Ok, Err> | V,
matchPattern: MatchResult<Ok, Err, R> | Partial<MatchPattern<V, R>>,
): R {
if (value instanceof Result) {
if (value.isOk()) {
return (matchPattern as MatchResult<Ok, Err, R>).ok(value.unwrap());
}
return (matchPattern as MatchResult<Ok, Err, R>).err(value.unwrapErr());
}

// deno-fmt-ignore
const func =
(matchPattern as MatchPattern<V, R>)[value] ??
(matchPattern as MatchPattern<V, R>)["_"];

if (func) return func(value);

throw Error('No matching pattern found. Use "_" as a rest pattern');
}
50 changes: 50 additions & 0 deletions match_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { match } from "./match.ts";
import { Err, Ok } from "./result.ts";
import { assertEquals } from "https://deno.land/std@0.100.0/testing/asserts.ts";

Deno.test({
name: "match result",
fn: function () {
const okayValue = match(Ok("ok"), {
ok: (val) => val,
err: () => "WRONG",
});

assertEquals(okayValue, "ok");
const errValue = match(Err("err"), {
ok: () => "WRONG",
err: (val) => val,
});

assertEquals(errValue, "err");
},
});

Deno.test({
name: "match string",
fn: function () {
const value1 = match("str", {
str: (val) => val,
_: () => "REST",
});
assertEquals(value1, "str");

const value2 = match("not", {
str: (val) => val,
_: () => "REST",
});

assertEquals(value2, "REST");

try {
match("no rest", {
str: (val) => val,
});
} catch (e) {
assertEquals(
e.message,
'No matching pattern found. Use "_" as a rest pattern',
);
}
},
});
4 changes: 4 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { Err, Ok } from "./result.ts";
export * from "./match.ts";

export type { Result } from "./result.ts";
40 changes: 40 additions & 0 deletions result.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
type ResultTypes = "ok" | "err";

export class Result<Ok, Err> {
#ok: Ok | null = null;
#err: Err | null = null;
#isOkay: boolean;

constructor(res: "ok", value: Ok);
constructor(res: "err", value: Err);
constructor(res: ResultTypes, value: Ok | Err) {
this.#isOkay = res === "ok";
this.#isOkay ? this.#ok = value as Ok : this.#err = value as Err;
}

public unwrap(): Ok {
if (this.#isOkay) return this.#ok!;
throw new Error("Tried to unwrap value when value was err");
}

public unwrapErr(): Err {
if (!this.#isOkay) return this.#err!;
throw new Error("Tried to unwrap error when value was ok");
}

public isErr(): boolean {
return !this.#isOkay;
}

public isOk(): boolean {
return this.#isOkay;
}
}

export function Ok<Ok, Err>(val: Ok): Result<Ok, Err> {
return new Result("ok", val);
}

export function Err<Ok, Err>(val: Err): Result<Ok, Err> {
return new Result("err", val);
}
38 changes: 38 additions & 0 deletions result_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Err, Ok } from "./result.ts";
import {
assertEquals,
assertThrows,
} from "https://deno.land/std@0.100.0/testing/asserts.ts";

Deno.test({
name: "Ok Test",
fn: function () {
const res = Ok("unwrap string");

assertEquals(res.unwrap(), "unwrap string");
assertEquals(res.isOk(), true);
assertEquals(res.isErr(), false);
},
});

Deno.test({
name: "Err test",
fn: function () {
const res = Err("unwrap string");

assertEquals(res.unwrapErr(), "unwrap string");
assertEquals(res.isErr(), true);
assertEquals(res.isOk(), false);
},
});

Deno.test({
name: "unwraps",
fn: function () {
const eres = Err("");
const ores = Ok("");

assertThrows(eres.unwrap);
assertThrows(ores.unwrapErr);
},
});

0 comments on commit 282c17b

Please sign in to comment.