Files
tiny-pattern-ts/src/primitive.ts
T
tmu 068d6b4998 ♻️ Use line comments in primitive matchers
Replace the three `/* */` prose blocks with `//` line comments, matching
the rest of the codebase and the comment style the oxlint config now
allows.
2026-09-16 21:46:00 +00:00

72 lines
3.0 KiB
TypeScript

import type { Simplify, ValueOf } from "type-fest";
type UnaryFn<T, R> = (shape: T) => R;
// ============================================================================
// ✔️ Exhaustive
// ❌ ReturnsStrict
// ============================================================================
type PatternPrimitiveUnion<R, T extends string | number> = {
[K in T]: UnaryFn<K, R>;
};
type PatternReturns<
P extends Record<string | number, UnaryFn<never, unknown>>,
> = ReturnType<ValueOf<P>>;
export const getPrimitiveUnionMatcherW: <T extends string | number>() => <
P extends PatternPrimitiveUnion<unknown, T>,
>(
pattern: Simplify<P>,
) => UnaryFn<T, PatternReturns<P>> = () => (pattern) => (shape) =>
// Rewrite not to use any is possible, was evaluated and solutions were
// more complex than the current solution.
// oxlint-disable-next-line typescript/no-explicit-any typescript/no-unsafe-type-assertion
(pattern[shape] as any)(shape);
// ============================================================================
// ✔️ Exhaustive
// ✔️ ReturnsStrict
// ============================================================================
export const getPrimitiveUnionMatcher: <T extends string | number>() => <R>(
pattern: Simplify<PatternPrimitiveUnion<R, T>>,
) => UnaryFn<T, R> = getPrimitiveUnionMatcherW;
// ============================================================================
// ❌ Exhaustive
// ✔️ ReturnsStrict
// ============================================================================
type PatternPrimitiveUnionPartial<R, T extends string | number> =
| PatternPrimitiveUnion<R, T>
| (Partial<PatternPrimitiveUnion<R, T>> & {
_: UnaryFn<T, R>;
});
export const getPrimitiveUnionMatcherPartial: <T extends string | number>() => <
R,
>(
pattern: Simplify<PatternPrimitiveUnionPartial<R, T>>,
) => UnaryFn<T, R> = () => (pattern) => (shape) =>
// Rewrite not to use any is possible, was evaluated and solutions were
// more complex than the current solution.
// oxlint-disable-next-line typescript/no-explicit-any typescript/no-unsafe-type-assertion
(pattern[shape] ?? (pattern as any)["_"])(shape);
// ============================================================================
// ❌ Exhaustive
// ❌ ReturnsStrict
// ============================================================================
export const getPrimitiveUnionMatcherPartialW: <
T extends string | number,
>() => <P extends PatternPrimitiveUnionPartial<unknown, T>>(
// `Simplify<P>` is the inference hook: callers infer `P` from the argument.
// the second half pins the impl parameter's `R` to `PatternReturns<P>`.
// that makes the `= getPrimitiveUnionMatcherPartial` assignment type-check.
// neither half works alone.
// without the witness the union's `_` arm demands `_ ∈ keyof P`.
// without `Simplify<P>` the parameter types do not compare.
pattern: Simplify<P> & PatternPrimitiveUnionPartial<PatternReturns<P>, T>,
) => UnaryFn<T, PatternReturns<P>> = getPrimitiveUnionMatcherPartial;