import { P, matcher } from "matchigo";
type Shape =
| { kind: "circle"; r: number }
| { kind: "square"; s: number };
const area = matcher<Shape, number>()
.with({ kind: "circle" }, (s) => Math.PI * s.r ** 2)
.with({ kind: "square" }, (s) => s.s ** 2)
.exhaustive(); // compile-time exhaustiveness check
area({ kind: "circle", r: 2 }); // 12.566…
Chained builder. Each
.with()appends a rule;.exhaustive()closes the chain and returns a callable dispatcher. Rules compile once on.exhaustive()/.otherwise(), so hoist the result to module scope to keep the hot path allocation-free.