Skip to content

refactor!: *Cases error-matcher rename + v5-beta migration fixes (#142–#146) - #147

Merged
btravers merged 6 commits into
mainfrom
refactor/err-combinators-cases
Jul 27, 2026
Merged

refactor!: *Cases error-matcher rename + v5-beta migration fixes (#142–#146)#147
btravers merged 6 commits into
mainfrom
refactor/err-combinators-cases

Conversation

@btravers

@btravers btravers commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Fixes the five issues surfaced while migrating an 18-package client project onto
unthrown@5.0.0-beta. Rebased onto main (beta.4) — the *Cases combinator
rename is already on main, so this PR is now just the five fixes plus a review
follow-up. One commit per issue:

fix(core): make ts-pattern a peerDependencyCloses #143

ts-pattern moves from a nested dependency to a peer (^5), so a consumer
already using ts-pattern shares one copy — two copies' declarations don't unify.
Kept as a devDependency for the workspace. New changeset (major).

fix(core): explain getOrThrow's never-channel gateCloses #144

The E = never gate now brands its never receiver with a message, so the
diagnostic says "getOrThrow is unnecessary here … use get() instead" instead
of an opaque this-context error. Behaviour unchanged.

refactor(core)!: rename match's err handler to errCasesCloses #142

match({ ok, err, defect })match({ ok, errCases, defect }). This is the one
5.0 break the compiler almost missed: a leftover 4.x throwing err handler
returned never, vacuously satisfied the matcher constraint, compiled, and threw
the matcher object at runtime. The renamed key makes it an excess-property
compile error. Type-d guard added.

docs(core): document the generic-E matcher limitationCloses #145

ts-pattern can't prove any builder exhaustive (even P._) behind an unresolved
generic E, so generic boundary helpers must use the isOk/isErr/isDefect
guards. Documented in the exhaustive-error-matching guide, plus a type-d guard.
(Confirmed getOrThrow() is also concrete-E-only, so guards are the one
generic-boundary tool — see the discussion on the rawErr thread.)

docs: add a 4.x to 5.0 migration guideCloses #146

New how-to upgrade guide (in the sidebar) + root MIGRATION.md with the headline
breaking surface, linked from the core README. @unthrown/pattern was already
removed from the repo.

docs: fix combinator matrix err() cell and defect-channel anchor

Review follow-up: the match row still showed err(), and the recoverErrCases
tip linked a stale #recovererr-… anchor.

Still needs a manual step (npm credentials):

npm deprecate @unthrown/pattern "merged into unthrown@5 — import match/P/tag from 'unthrown'"

Release

On merge, the changesets workflow publishes the next beta (5.0.0-beta.5 — a
pending major in pre mode). Gate green: format --check, lint, typecheck,
knip, test, build.

Copilot AI review requested due to automatic review settings July 27, 2026 17:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR completes the v5-beta API migration around exhaustive error matching by finalizing the *Cases renames (including match({ …, errCases })), switching ts-pattern to a peer dependency to avoid dual-copy type collisions, and adding/aligning documentation and migration guidance for 4.x → 5.0 adopters.

Changes:

  • Make ts-pattern a peerDependency (^5) for unthrown core, and update install/docs accordingly.
  • Finalize the *Cases rename across code, tests, and docs (mapErrCases, recoverErrCases, match({ errCases }), etc.), including type-level guards for previously silent breaks.
  • Improve migration experience: clearer getOrThrow() never-channel diagnostic and new 4.x → 5.0 upgrade docs (MIGRATION.md + VitePress how-to).

Reviewed changes

Copilot reviewed 55 out of 56 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md Update install instructions and match example to errCases + peer dep note.
pnpm-lock.yaml Lockfile updates reflecting ts-pattern dependency move.
packages/prisma/README.md Update match handler key to errCases.
packages/orpc/src/types.test-d.ts Update guidance text to mapErrCases.
packages/orpc/src/server.ts Update docs/comments and references to mapErrCases / errCases.
packages/orpc/src/index.spec.ts Update test usage to errCases.
packages/orpc/src/extensions/result.ts Update inline example to mapErrCases.
packages/orpc/src/client.ts Update docs to errCases.
packages/orpc/README.md Update README examples and wording to mapErrCases / errCases.
packages/neverthrow/src/index.ts Update comment referencing errCases matcher.
packages/effect/src/index.ts Update comment referencing errCases matcher.
packages/effect/README.md Update example to errCases.
packages/core/src/types.ts Rename method surface types/docs (*Cases, errCases) + improve getOrThrow diagnostic.
packages/core/src/types.test-d.ts Update type tests for new names; add guard for old match({ err }) shape; document generic-E limitation.
packages/core/src/tagged.ts Update docs/examples to mapErrCases.
packages/core/src/tagged.spec.ts Update tests for errCases.
packages/core/src/result.spec.ts Update tests for *Cases combinators and match({ errCases }).
packages/core/src/invariants.spec.ts Update invariant tests for *Cases combinators.
packages/core/src/index.ts Update ts-pattern re-export comment to new naming.
packages/core/src/core.ts Rename internal implementations to *Cases and match handler to errCases.
packages/core/src/async-result.spec.ts Update async surface tests for *Cases combinators and errCases.
packages/core/README.md Update install instructions, examples, and link to v5 upgrade guide.
packages/core/package.json Move ts-pattern from dependency → peerDependency; keep as devDependency for workspace tooling.
packages/boxed/src/index.ts Update comment referencing errCases matcher.
MIGRATION.md Add top-level 4.x → 5.0 migration summary and link to docs guide.
docs/tutorial/getting-started.md Update install commands and examples to include ts-pattern and errCases.
docs/tutorial/crossing-an-async-boundary.md Update example to errCases.
docs/reference/result-surface.md Update combinator naming in reference surface section.
docs/reference/glossary.md Update glossary entry to mapErrCases.
docs/reference/combinators.md Update reference tables and narrative for *Cases naming and recoverErrCases.
docs/index.md Update homepage example to errCases.
docs/how-to/validate-with-standard-schema.md Update example to errCases.
docs/how-to/use-with-prisma.md Update narrative/examples to errCases.
docs/how-to/use-with-orpc.md Update examples and narrative to mapErrCases / errCases.
docs/how-to/upgrade-to-v5.md Add new 4.x → 5.0 checklist/migration guide.
docs/how-to/sequence-dependent-steps.md Update examples to errCases.
docs/how-to/qualify-a-boundary.md Update example to errCases.
docs/how-to/model-errors.md Update narrative/examples to errCases and mapErrCases naming.
docs/how-to/migrate-from-try-catch.md Update guidance/examples to mapErrCases / tapErrCases / errCases.
docs/how-to/migrate-from-neverthrow.md Update mapping table and examples to mapErrCases / flatMapErrCases / errCases.
docs/how-to/interoperate-with-libraries.md Update example to errCases.
docs/how-to/handle-results-at-the-edge.md Update examples and references to errCases and recoverErrCases / flatMapErrCases.
docs/explanation/why-unthrown.md Update example to errCases.
docs/explanation/the-defect-channel.md Update method names and section headings to *Cases.
docs/explanation/qualification.md Update narrative to mapErrCases.
docs/explanation/exhaustive-error-matching.md Update explanation to reflect *Cases naming and add generic-helper limitation guidance.
docs/explanation/design-decisions.md Update design decision rationale to *Cases suffix.
docs/explanation/async-model.md Update naming in async model explanation (flatMapErrCases).
docs/.vitepress/config.ts Add sidebar entry for the v5 upgrade guide.
CLAUDE.md Update internal spec text to *Cases/errCases and peer dep rationale.
.changeset/ts-pattern-peer-dependency.md Changeset: ts-pattern becomes peerDependency (major).
.changeset/synchronous-qualify-and-taperr.md Changeset text updated to tapErrCases naming.
.changeset/runtime-hardening.md Changeset text updated to flatMapErrCases / flatTapErrCases naming.
.changeset/rename-err-combinators-cases.md Changeset: document *Cases rename and errerrCases.
.changeset/getorthrow-never-gate-message.md Changeset: document improved getOrThrow() gate diagnostic.
.changeset/exhaustive-error-matcher.md Changeset text updated to mapErrCases and errCases naming.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Comments suppressed due to low confidence (1)

docs/reference/combinators.md:73

  • This link anchor still uses #recovererr-…, but the target section header is now "recoverErrCases…", so the generated slug will change and this link will likely break. Update the anchor to match the new heading slug.
[The Defect Channel](../explanation/the-defect-channel#recovererr-clears-the-error-channel-not-the-runtime).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/reference/combinators.md Outdated
Comment thread docs/explanation/exhaustive-error-matching.md
btravers added 6 commits July 27, 2026 20:15
unthrown re-exports ts-pattern's match/P/tag and its error matchers speak
ts-pattern's builder type. Pinned as a nested dependency, a consumer already
using ts-pattern got two copies whose declarations don't unify — feeding a
P.union(...) from one into an unthrown matcher failed deep in a conditional
type. Declaring it a peer (^5) guarantees a single, consumer-owned copy.

Kept as a devDependency (catalog) for the workspace's own build/test. Updated
CLAUDE.md, the READMEs, and the install docs to say you install ts-pattern
yourself.

Closes #143
When E = never there is nothing to throw, so getOrThrow() is gated off and
get() is the tool. The gate previously surfaced as an opaque "'this' context
... is not assignable to method's 'this' of type 'never'". The never receiver
now carries a message, so the compiler prints why and points at get().
Behaviour is unchanged.

Closes #144
match's error handler now carries the same …Cases suffix as the error
combinators — it takes the exhaustive ts-pattern matcher, not a plain
(error) => … callback. This closes a silent runtime break: a leftover 4.x
err: (error) => … handler that threw still satisfied the matcher constraint
(a throwing handler returns never, which vacuously satisfies it), compiled,
and then threw the matcher object at runtime. The renamed key makes it an
excess-property compile error instead.

Renames match({ ok, err, defect }) → match({ ok, errCases, defect }) across
the API, tests, docs, interop packages, and the spec. Adds a type-d guard
that the old err key no longer compiles.

Closes #142
Inside a helper whose error type is still a type parameter, ts-pattern cannot
prove any builder exhaustive — not even .with(P._, …) — so match/…Cases do not
compile there. Generic boundary helpers (the interop to* bridges, oRPC's
handlerResult) use the isOk/isErr/isDefect guards instead, which carry no
exhaustiveness obligation. Documents this in the exhaustive-error-matching
guide with the guard-based pattern, plus a type-d regression guard.

Closes #145
@unthrown/pattern was absorbed into core and the 5.0 breaking surface (renamed
error combinators, match's err → errCases, removed aliases, UnwrapError →
GetError, the getOrThrow gate, ts-pattern as a peer) was only discoverable by
diffing tarballs. Adds a how-to upgrade guide (in the sidebar) and a root
MIGRATION.md with the headline list up front, linked from the core README.

Closes #146
Review follow-up (#142 rename): the `match` row in the combinator matrix still
showed `err()`, and the recoverErrCases tip linked a stale
`#recovererr-…` anchor whose target header is now `recoverErrCases …`.
@btravers
btravers force-pushed the refactor/err-combinators-cases branch from 13c39d2 to e1308f3 Compare July 27, 2026 18:16
@btravers
btravers merged commit 5364caa into main Jul 27, 2026
15 checks passed
@btravers
btravers deleted the refactor/err-combinators-cases branch July 27, 2026 18:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment