♻️ 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

+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