tRPC: end-to-end types without GraphQL
2 min read
By Juliano Alves
tRPC wires TypeScript types from server procedures to client callers over HTTP—no code generation step, strong autocomplete, and optional Zod validation on inputs.
Router shape
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
const t = initTRPC.context<Context>().create();
export const appRouter = t.router({
hello: t.procedure.input(z.object({ name: z.string() })).query(({ input }) => {
return `Hello ${input.name}`;
}),
});
export type AppRouter = typeof appRouter;
Client infers AppRouter types via @trpc/react-query or vanilla client.
Context
Inject user, db, and logger in createContext per request—keep procedures thin and test context builders in isolation.
Public APIs
tRPC shines for first-party apps. For third-party integrators, still expose OpenAPI/REST or webhooks—do not force external teams into your TS router.
Summary
tRPC minimizes contract drift between front and back on the same repo. Pair with Zod, version breaking procedure changes consciously, and keep a clear boundary where public HTTP must remain stable.