♻️ Share the Matchable universe between both matchers

This commit is contained in:
tmu committed 2026-09-22 10:54:27 +00:00
1 parent d88a4eeb45
commit 6228b4922d
4 files changed
+24 -17

No files matched your search

+6
View File
@@ -8,6 +8,12 @@ import type { ValueOf } from "type-fest";
// A handler: one universe member in, one return value out.
export type UnaryFn<T, R> = (shape: T) => R;
// The primitive universe a matcher can discriminate. The primitive-union matcher
// uses it directly; the tagged-union matcher uses it as the set of allowed
// discriminant (`Tag`) values. `boolean` is admitted as the pair `true | false`;
// see README § Caveats for the unsupported members.
export type Matchable = string | number | boolean | null | undefined;
// `boolean`, `null` and `undefined` cannot be property keys, so a mapped type
// over a universe that includes one keys each such member by its
// stringification. `PatternParam` inverts that projection, so a handler callback
+1 -4
View File
@@ -2,6 +2,7 @@ import type { Exact } from "type-fest";
import type {
HandlerMap,
Matchable,
PatternKey,
PatternParam,
PatternReturns,
@@ -9,10 +10,6 @@ import type {
UnaryFn,
} from "./matcher-shared.ts";
// The primitive universe a matcher can discriminate. `boolean` is admitted as
// the pair `true | false`; see README § Caveats for the unsupported members.
type Matchable = string | number | boolean | null | undefined;
type Handlers<T extends Matchable, R> = {
[K in PatternKey<T>]: UnaryFn<PatternParam<K>, R>;
};
+8 -8
View File
@@ -2,6 +2,7 @@ import type { Exact, UnknownRecord } from "type-fest";
import type {
HandlerMap,
Matchable,
PatternKey,
PatternParam,
PatternReturns,
@@ -9,22 +10,21 @@ import type {
UnaryFn,
} from "./matcher-shared.ts";
// A tagged union is discriminated by one property whose values are the tags.
// `string` and `number` tags key a handler map directly; `boolean`, `null` and
// `undefined` are admitted too but are not property keys, so they go through the
// `PatternKey` projection. `symbol` has no literal syntax to write a handler
// under, and `bigint` is not a property key.
type Tag = string | number | boolean | null | undefined;
// A tagged union is discriminated by one property whose values are the tags (a
// `Matchable`). `string` and `number` tags key a handler map directly;
// `boolean`, `null` and `undefined` are admitted too but are not property keys,
// so they go through the `PatternKey` projection. `symbol` has no literal syntax
// to write a handler under, and `bigint` is not a property key.
// The discriminant values of `T` under `K`. `Extract` keeps the finite literal
// tags and leaves a widened `string`/`number` as itself, so an open universe
// keeps an open fallback.
type Tags<T extends object, K extends keyof T> = Extract<T[K], Tag>;
type Tags<T extends object, K extends keyof T> = Extract<T[K], Matchable>;
// The keys of `T` that can act as a discriminant. `getTaggedUnionMatcher<T>()`
// accepts only these, so the factory rejects a key whose values are not tags.
type Discriminated<T extends object> = {
[K in keyof T]: T[K] extends Tag ? K : never;
[K in keyof T]: T[K] extends Matchable ? K : never;
}[keyof T];
// The member(s) of `T` tagged `V`. `Extract` distributes over the union, so a