Skip to content

Instantly share code, notes, and snippets.

@toky-nomena
Last active August 2, 2024 13:29
Show Gist options
  • Save toky-nomena/4ba8e42c249e2e0464bbf5f01d1e893f to your computer and use it in GitHub Desktop.
Save toky-nomena/4ba8e42c249e2e0464bbf5f01d1e893f to your computer and use it in GitHub Desktop.
export const matcher = <Input, Output>(value: Input) => {
type Result = (value: Input) => Output;
type Expression = (value: Input) => boolean;
interface MatchCases {
expression: Expression;
result: Result;
}
const cases: MatchCases[] = [];
let defaultCase: Result = () => {
throw new Error("No default case provided");
};
function run(): Output {
for (const { expression, result } of cases) {
if (expression(value)) {
return result(value);
}
}
return defaultCase(value);
}
function setDefault(result: Result) {
defaultCase = result;
return run();
}
function addCase(expression: Expression, result: Result) {
cases.push({ expression, result });
return { case: addCase, default: setDefault };
}
return { case: addCase };
};
export const asyncMatcher = <Input, Output>(value: Input) => {
type Result = (value: Input) => Output | Promise<Output>;
type Expression = (value: Input) => boolean | Promise<boolean>;
interface MatchCases {
expression: Expression;
result: Result;
}
const cases: MatchCases[] = [];
let defaultCase: Result = () => {
throw new Error("No default case provided");
};
async function run() {
for (const { expression, result } of cases) {
if (await expression(value)) {
return await result(value);
}
}
return defaultCase(value);
}
function setDefault(result: Result) {
defaultCase = result;
return run();
}
function addCase(expression: Expression, result: Result) {
cases.push({ expression, result });
return { case: addCase, default: setDefault };
}
return { case: addCase };
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment