can1357/oh-my-pi · error · OmpTypeError
match case values must be functions
Error message
match case values must be functions
What it means
caseResolver() converts match-case values into resolver functions; a case value that is not a function throws OmpTypeError. Match cases are expected to supply handlers (functions of the input) rather than plain values, so a non-function is a misuse of the match API.
Source
Thrown at packages/omptype/src/type.ts:2863
in<narrowed>(): MatchParser<narrowed, output>;
in<const definition>(definition: definition): MatchParser<InferDef<definition>, output>;
}
interface MatchBranch {
readonly definition: unknown;
readonly schema: BaseType;
readonly resolve: (input: unknown, ...args: readonly unknown[]) => unknown;
}
interface MatchState {
readonly parse: (definition: unknown) => BaseType;
readonly branches: readonly MatchBranch[];
readonly input?: BaseType;
readonly key?: PropertyKey;
}
function caseResolver(value: unknown): (input: unknown, ...args: readonly unknown[]) => unknown {
if (typeof value !== "function") throw new OmpTypeError("match case values must be functions");
return (input, ...args) => Reflect.apply(value, undefined, [input, ...args]);
}
function unionIR(branches: readonly MatchBranch[]): IR {
const members = branches.map(branch => branch.schema.ir);
if (members.length === 0) return { k: "never" };
if (members.length === 1) return members[0];
return { k: "union", members };
}
function publicMatcher<input, output>(
state: MatchState,
fallback: MatchDefault<input, output>,
): Matcher<input, output> {
const fallbackResolver = typeof fallback === "function" ? caseResolver(fallback) : undefined;
const casesIR = unionIR(state.branches);
let casesSchema: BaseType;
if (state.key === undefined || state.branches.length === 0) {View on GitHub (pinned to 9690622007)
Solutions
- Wrap the value in a function: () => 'fallback' instead of 'fallback'
- If you need a schema as a case, use the API that accepts a schema, not caseResolver's function path
- Validate dynamically built case maps with typeof value === 'function' before passing them
- Check that your case object keys map to handler functions, not result constants
Example fix
// before
match({ 'string': 'it was a string' }); // throws
// after
match({ 'string': () => 'it was a string' }); Defensive patterns
Strategy: validation
Validate before calling
function assertFunctionCases(cases: Record<string, unknown>) {
for (const [key, value] of Object.entries(cases)) {
if (typeof value !== 'function') {
throw new Error(`match case "${key}" must be a function`);
}
}
} Type guard
function isHandlerMap(cases: Record<string, unknown>): cases is Record<string, (input: unknown) => unknown> {
return Object.values(cases).every(v => typeof v === 'function');
} Try / catch
try {
const m = match(cases);
} catch (err) {
if (err instanceof OmpTypeError && err.message === 'match case values must be functions') {
throw new Error('Wrap constant results in functions: value -> () => value');
}
throw err;
} Prevention
- Always write match cases as handler functions, even for constants
- Validate data-driven case maps with typeof before use
- Type case maps as Record<string, (input: unknown) => unknown> so the compiler catches constants
When it happens
Trigger: Passing a non-function as a match case value, e.g. match({ 'string': 'fallback' }) or cases built from data where an entry is a constant/schema instead of a handler function.
Common situations: Confusing value-match with handler-match syntax; JSON-driven case tables where values deserialize as strings/numbers; refactoring from a value API to a function API without wrapping constants.
Related errors
- mapped property ${String(property.key)} has invalid kind
- mapped property ${String(property.key)} must contain a schem
- intersection has no satisfiable branches
- ParseError: Invalid intersection of default values ${String(
- cannot apply numeric bound to ${ir.k}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/7a2dcd04150e96e7.
Report an issue: GitHub.