If you've spent any time building full-stack TypeScript applications, you know the pain of keeping your API contracts in sync between the server and client. A change to a response shape on the backend silently breaks the frontend, and you don't find out until runtime — or worse, until a user reports a bug.
The problem with REST
Traditional REST APIs require you to manually define types on both sides of the wire. You write an endpoint that returns a user object, then you write a TypeScript interface on the client that describes what that object looks like. These two definitions live in separate codebases, and nothing enforces that they stay in sync.
OpenAPI and code generation tools help, but they add complexity and build steps. What if the types could flow directly from your server code to your client code, with zero code generation?
Enter tRPC + Zod
tRPC lets you define procedures on the server and call them from the client as if they were local functions. Combined with Zod for runtime validation, you get a setup where your API contract is defined once — as a Zod schema — and both the server and client derive their types from it automatically.
const userRouter = router({
getById: publicProcedure
.input(z.object({ id: z.string() }))
.query(async ({ input }) => {
return db.user.findUnique({
where: { id: input.id }
});
}),
});The client now has full type inference. When you call trpc.user.getById.useQuery({ id: '123' }), the return type is automatically inferred from the server's Prisma query. Change the schema on the server, and the client immediately shows a type error.
Why this matters
The real value isn't just type safety — it's the developer experience. You get autocompletion on API calls, instant feedback when contracts break, and zero boilerplate for keeping things in sync. It removes an entire category of bugs that waste hours of debugging time.
The best API contract is the one you never have to think about. When types flow from server to client automatically, you spend less time on plumbing and more time on the product.
If you're starting a new TypeScript project — or looking to improve an existing one — I'd strongly recommend giving tRPC and Zod a try. The initial setup takes about fifteen minutes, and the payoff compounds with every endpoint you add.