Announcing Result-RPC — typed RPC for TypeScript where errors and entities are first-class.
tRPC and oRPC nail the typed-call part. I wanted the two things that come after the call: what happens when it fails, and what happens to your cache when it succeeds.
http://result-rpc.com
Every call returns Result<T, E> — no data/error duality. E is one union: your per-procedure errors, plus cross-cutting ones (offline, timeout, client/server drift - these come out of the box), plus class-level ones (workspace-not-found, unauthorized - anything your app needs).
That's a huge union of errors to deal with.
It isn't, because of Shells — React components that claim errors where they belong in the tree. Offline → a banner. Unauthorized → a login redirect. Each shell subtracts what it handles from the type above the caller component, so by the time you reach your leaf, only the procedure-specific errors remain.
The types do the subtraction for you.
The wire format carries entities, not just JSON. Return { user: [User], totalPosts: number } and every live User in your component tree updates — across every procedure. Mix mapped entities and one-off values freely. Date, Map, Set, URL all survive the wire.
This is my attempt to get the best of all worlds: urql and Relay for normalized identity, tRPC for E2E types and React ergonomics, Effect for taking error channels seriously.