Repository navigation
fix(effect): close type holes in catchORPCErrorCode and catchORPCErrorCodes - #2261
Conversation
…rCodes - Keep `ORPCError<any, any>` and wide-coded errors (e.g. `ORPCError<ORPCErrorCode, unknown>`, `ORPCError<string, unknown>`, union codes) in the result error channel, since catching one code does not catch the others. - Narrow the handler error to the caught code instead of `never` for wide and union codes. - Only exclude a member when every possible code is caught: `catchORPCErrorCode` requires a single literal code, and `catchORPCErrorCodes` only counts required keys whose value is a function, matching the runtime check. - Merge success, error and services of handlers that may be `undefined` into the result. - Import `ORPCError` from `@orpc/client` so client-only bundles do not pull in `@orpc/server`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lg5QRphdQBu6PCo88vV51o
- Define the "which ORPCErrors can a handler receive" rule once (`ORPCErrorsOf`) and reuse it in `catchORPCError` and for the code suggestions. - Flatten `ORPCErrorWithCode` to a single inference check, and test code coverage with `Exclude` so `any` codes need no special-case guard. - Reuse effect's `Types.IsUnion`, `Types.RequiredKeys`, `Types.NoExcessProperties` and the built-in `ReturnType` instead of hand-written equivalents. - Share the `catchORPCErrorCodes` result type between both overloads, and use `AnyEffect` in the runtime signatures. No type or runtime behavior change; per-call type instantiations drop by 16-27%. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lg5QRphdQBu6PCo88vV51o
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lg5QRphdQBu6PCo88vV51o
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
orpc | 14845a6 | Commit Preview URL Branch Preview URL |
Oct 17 2026, 02:48 AM |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
More templates
@orpc/ai-sdk
@orpc/arktype
@orpc/bun
@orpc/client
@orpc/cloudflare
@orpc/contract
@orpc/experimental-effect
@orpc/evlog
@orpc/hibernation
@orpc/json-schema
@orpc/experimental-lock
@orpc/experimental-msw
@orpc/nest
@orpc/next
@orpc/node
@orpc/openapi
@orpc/opentelemetry
@orpc/pinia-colada
@orpc/pino
@orpc/publisher
@orpc/ratelimit
@orpc/server
@orpc/shared
@orpc/swr
@orpc/tanstack-query
@orpc/trpc
@orpc/valibot
@orpc/zod
commit: |
Merging this PR will not alter performance
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — the type-level rewrite of the Effect error helpers in packages/effect/src/error.ts, the import migration to @orpc/client, and the expanded type/runtime tests. I verified the types against the runtime predicates and ran the checks below.
- Import migration:
error.tsand its tests now importORPCError,AnyORPCError, andORPCErrorCodefrom@orpc/client.@orpc/serverre-exports all three from@orpc/client(packages/server/src/index.ts:26-55), so class identity and the runtimeinstanceof ORPCErrorcheck are unchanged, and@orpc/clientis already a dependency ofpackages/effect. - Extracted type helpers:
ORPCErrorsOf,ORPCErrorCodeOf,ORPCErrorWithCode,ExcludeORPCErrorCode,LiteralORPCErrorCode,ORPCErrorCodeCases,HandledORPCErrorCodes,ORPCErrorCodeCasesEffect, andCatchORPCErrorCodesEffectreplace the previous inline conditionals. catchORPCErrorCodenarrowing: the error channel drops a member only when the caught code is a single literal (LiteralORPCErrorCodereturnsneverfor unions,string, andORPCErrorCode) and that member's whole code union is contained in it; wide/union codes,ORPCError<string>,ORPCError<ORPCErrorCode>,AnyORPCError, and hidden-Errorchannels all keep the error in the channel.catchORPCErrorCodeshandling: only required keys with a function value enterHandledORPCErrorCodes—undefinedand optional handlers keep their code in the error channel, which fixes prior unsoundness wherekeyof Casesexcluded those codes even though thegetOwnruntime predicate skips them.- Test coverage: added type tests for wide codes, union narrowing, ORPCError subclasses,
AnyORPCError, undeclared keys on hidden channels, and optional/undefined handlers, plus the runtime import update.
Verification: tsc -b packages/effect --force, root tsc --noEmit -p tsconfig.json (covers *.test-d.ts), vitest run packages/effect/src/error.test.ts (20/20), and eslint on the three changed files all pass.
deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

Migrates the Effect integration from
@orpc/serverto@orpc/clientand significantly improves type inference and narrowing for error handling utilities.Changes
@orpc/serverto@orpc/clientforORPCErrorand related typesORPCErrorsOf,ORPCErrorWithCode,ExcludeORPCErrorCode,LiteralORPCErrorCode,ORPCErrorCodeCases, etc.) to provide better type narrowing and error channel managementcatchORPCErrorCode: Now properly narrows error types based on the caught code, keeping unhandled errors in the error channel with correct type informationcatchORPCErrorCodes: Refactored type signatures to:ORPCErrorCode, etc.)AnyORPCErrorhandlingORPCErrorCode)The changes maintain backward compatibility while providing more precise type safety for error handling workflows.
https://claude.ai/code/session_01Lg5QRphdQBu6PCo88vV51o