📝 Document matcher caveats in the README
State the end-user limits once, in README § Caveats: a member colliding with its stringification, the unsupported symbol/bigint, and NaN/-0. Drop the duplicated known-issue prose from development/library.md and the source comment; link to the README instead.
This commit is contained in:
1 parent
16904440cf
commit
1ad19ba308
3 files changed
+19
-22
No files matched your search
@@ -9,7 +9,7 @@ ordinary objects whose `matches` method is a TypeScript type guard, so narrowing
|
|||||||
composes the way any other guard does. It is deliberately not a regex engine and
|
composes the way any other guard does. It is deliberately not a regex engine and
|
||||||
not a macro: there is no transpiler and no DSL to learn, and the type-level
|
not a macro: there is no transpiler and no DSL to learn, and the type-level
|
||||||
contract is the feature — see [development/library.md](./development/library.md)
|
contract is the feature — see [development/library.md](./development/library.md)
|
||||||
for the design decisions and the known limitations.
|
for the design decisions and [Caveats](#caveats) for the limits.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -23,6 +23,18 @@ for the design decisions and the known limitations.
|
|||||||
|
|
||||||
Yet to be implemented
|
Yet to be implemented
|
||||||
|
|
||||||
|
## Caveats
|
||||||
|
|
||||||
|
- **A value and its stringification collide.** Object keys stringify, so a
|
||||||
|
universe that mixes a member with the string it stringifies to — `1 | "1"`,
|
||||||
|
`true | "true"`, `null | "null"` — collapses to a single handler key and both
|
||||||
|
members are routed to it. Use one form or the other.
|
||||||
|
- **`symbol` and `bigint` are not supported.** A `symbol` brand is a
|
||||||
|
compile-time phantom with nothing to match at runtime, and a `bigint` is not a
|
||||||
|
valid property key; neither satisfies the matcher's universe constraint.
|
||||||
|
- **`NaN` and `-0` cannot be matched specifically.** They have no literal type,
|
||||||
|
so both stay part of `number`.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT © 2025 tmu. See [LICENSE](./LICENSE).
|
MIT © 2025 tmu. See [LICENSE](./LICENSE).
|
||||||
|
|||||||
+4
-16
@@ -97,7 +97,7 @@ Each factory is two overloads whose order is load-bearing:
|
|||||||
#### Decision (2026-09)
|
#### Decision (2026-09)
|
||||||
|
|
||||||
The universe (`Matchable`) is `string | number | boolean | null | undefined`,
|
The universe (`Matchable`) is `string | number | boolean | null | undefined`,
|
||||||
with `boolean` admitted as `true | false`. `symbol` and `bigint` are not.
|
with `boolean` admitted as `true | false`.
|
||||||
|
|
||||||
`boolean`/`null`/`undefined` are not property keys, so handler-map keys are a
|
`boolean`/`null`/`undefined` are not property keys, so handler-map keys are a
|
||||||
projection (`PatternKey`: each member stringified) and `PatternParam` inverts
|
projection (`PatternKey`: each member stringified) and `PatternParam` inverts
|
||||||
@@ -109,18 +109,6 @@ offers `true`, `false`, `null`, `undefined` by name (verified over LSP).
|
|||||||
- Runtime dispatch is unchanged in effect: `handlers[true]` already coerces to
|
- Runtime dispatch is unchanged in effect: `handlers[true]` already coerces to
|
||||||
`"true"`. `dispatch` wraps the index in `String()` only because TypeScript
|
`"true"`. `dispatch` wraps the index in `String()` only because TypeScript
|
||||||
forbids indexing with `boolean`/`null`/`undefined` (`TS2538`).
|
forbids indexing with `boolean`/`null`/`undefined` (`TS2538`).
|
||||||
|
- `symbol`/`bigint`/`NaN`/`-0` are rejected, and a member colliding with its
|
||||||
#### Rejected
|
stringification is unguarded: user-facing, stated once in
|
||||||
|
[README § Caveats](../README.md#caveats).
|
||||||
- **`symbol`.** A brand is a compile-time phantom — nothing to match at
|
|
||||||
runtime; the popup cannot offer symbol keys anyway.
|
|
||||||
- **`bigint`.** Not a valid property key; a stringified key (`"1"`) collides
|
|
||||||
with numeric `1`.
|
|
||||||
- **`NaN` / `-0`.** No literal type exists; they stay one `number`.
|
|
||||||
|
|
||||||
#### Known issue
|
|
||||||
|
|
||||||
- A universe mixing a member with its stringification (`1 | "1"`,
|
|
||||||
`true | "true"`, `null | "null"`) collapses to one handler key and routes
|
|
||||||
both members to it. Pre-existing for `1 | "1"`; now reachable for the new
|
|
||||||
members. Not guarded at the type level.
|
|
||||||
+2
-5
@@ -3,16 +3,13 @@ import type { Exact, ValueOf } from "type-fest";
|
|||||||
type UnaryFn<T, R> = (shape: T) => R;
|
type UnaryFn<T, R> = (shape: T) => R;
|
||||||
|
|
||||||
// The primitive universe a matcher can discriminate. `boolean` is admitted as
|
// The primitive universe a matcher can discriminate. `boolean` is admitted as
|
||||||
// the pair `true | false`; `symbol` is deliberately absent (a brand is a
|
// the pair `true | false`; see README § Caveats for the unsupported members.
|
||||||
// compile-time phantom, so there is nothing to match at runtime).
|
|
||||||
type Matchable = string | number | boolean | null | undefined;
|
type Matchable = string | number | boolean | null | undefined;
|
||||||
|
|
||||||
// `boolean`, `null` and `undefined` cannot be property keys, so a mapped type
|
// `boolean`, `null` and `undefined` cannot be property keys, so a mapped type
|
||||||
// over the universe keys each non-key member by its stringification. `Param`
|
// over the universe keys each non-key member by its stringification. `Param`
|
||||||
// inverts that projection, so a handler callback still receives the *real*
|
// inverts that projection, so a handler callback still receives the *real*
|
||||||
// member (`true`, not `"true"`). A universe mixing a member with the string it
|
// member (`true`, not `"true"`) — see README § Caveats for the limits.
|
||||||
// stringifies to (e.g. `true | "true"`) collapses to one key and is not
|
|
||||||
// representable — see development/library.md.
|
|
||||||
type PatternKey<T> = T extends boolean
|
type PatternKey<T> = T extends boolean
|
||||||
? T extends true
|
? T extends true
|
||||||
? "true"
|
? "true"
|
||||||
|
|||||||
Reference in new issue
Block a user