✨ Finalize and document the public API surface

Export the matcher builder types from the barrel and rename them off the
internal Strict/Widening suffixes, so the type a factory returns is
nameable: PrimitiveUnionMatcher/W, TaggedUnionMatcher/W, and the
tagged-union factory types. Add TSDoc to every public symbol — the
declarations carry it into the published package — and pin the exported
names in src/index.test.ts.

Document the API in README and record the surface decision (and the
rejected matcher-shared export) in development/library.md.
This commit is contained in:
tmu committed 2026-09-23 21:39:15 +00:00
1 parent acf9d06ddd
commit f485b1bae2
8 files changed
+317 -20

No files matched your search

+73 -1
View File
@@ -21,7 +21,79 @@ for the design decisions and [Caveats](#caveats) for the limits.
## API
Yet to be implemented
The package exports four factories and the builder types they return. Each
factory comes in a _strict_ variant (one common return type `R`) and a
_widening_ variant (the union of every handler's return type):
| Factory | Builder type | Return of the matcher |
| -------------------------------- | ------------------------------- | -------------------------------- |
| `getPrimitiveUnionMatcher<T>()` | `PrimitiveUnionMatcher<T>` | one common `R` |
| `getPrimitiveUnionMatcherW<T>()` | `PrimitiveUnionMatcherW<T>` | the union of the handler returns |
| `getTaggedUnionMatcher<T>()` | `TaggedUnionMatcherFactory<T>` | one common `R` |
| `getTaggedUnionMatcherW<T>()` | `TaggedUnionMatcherWFactory<T>` | the union of the handler returns |
### Primitive-union matchers
`getPrimitiveUnionMatcher<T>()` takes the finite universe `T` and returns a
builder. Calling the builder with a handler map keyed by `T`'s members returns a
matcher: a function from `T` to the common return type.
```ts
import { getPrimitiveUnionMatcher } from "tiny-pattern-ts";
const reply = getPrimitiveUnionMatcher<"yes" | "no">()({
yes: () => "agreed",
no: () => "declined",
});
reply("yes"); // "agreed"
```
Add a fallback as the second argument to leave members unhandled; the fallback
receives the remainder:
```ts
const label = getPrimitiveUnionMatcher<"yes" | "no" | "maybe">()(
{ yes: () => "agreed", no: () => "declined" },
(other) => `not sure: ${other}`, // other: "maybe"
);
```
`getPrimitiveUnionMatcherW` is the same builder, but the matcher's return type
is the union of the handler return types rather than one common `R`.
### Tagged-union matchers
`getTaggedUnionMatcher<T>()` takes a discriminated union `T`. The returned
function takes the discriminant property's name and returns the handler-map
builder, keyed by that property's tags.
```ts
import { getTaggedUnionMatcher } from "tiny-pattern-ts";
type Shape =
{ kind: "circle"; radius: number } | { kind: "square"; side: number };
const area = getTaggedUnionMatcher<Shape>()("kind")({
circle: (s) => Math.PI * s.radius ** 2,
square: (s) => s.side ** 2,
});
area({ kind: "circle", radius: 2 });
```
`getTaggedUnionMatcherW` is the widening counterpart, exactly as in the
primitive-union pair. The discriminant key is restricted to properties whose
values are tags; see [Caveats](#caveats) for the supported tags and the
`boolean` / `null` / `undefined` key projection.
### The universe
The primitive universe `T` must be a finite union of literals with no
value/stringification collision. A broad member (`string`, `number`, a template
literal) or a colliding pair (`true | "true"`, `1 | "1"`) is rejected at the
factory. The reasons and the rejected alternatives are in
[development/library.md](./development/library.md).
## Caveats