Skip to main content
Back to Blog
TechnologyWeb

Type Safety End to End

Oct 2025Awais Niaz
Type Safety End to End

Type safety is not about catching typos. It's about making impossible states unrepresentable. When your types flow from the database to the UI without gaps, entire categories of bugs disappear.

The Chain of Trust

A typical data flow:

Database → API → Client → UI Component

Every arrow is a boundary where types can break. The goal is to eliminate those boundaries.

Prisma: Database to Server

Prisma generates TypeScript types from your database schema automatically. When you change a column, the type changes everywhere. No manual sync. No migration scripts that drift from the code.

const user = await prisma.user.findUnique({ where: { id } });
// `user` is fully typed — name, email, role, all present or null

tRPC: Server to Client

tRPC carries types across the network boundary. The client calls a function, not an endpoint. The return type is inferred from the server implementation.

const user = await trpc.user.get.query({ id });
// `user` has the same type as the Prisma query — no manual type file

No hand-written API types. No duplication. If the server changes the return shape, the client code fails to compile.

Zod: Runtime Validation

TypeScript types disappear at runtime. Zod schemas validate external input — API bodies, form submissions, webhook payloads — and parse them into trusted types.

const schema = z.object({
  email: z.string().email(),
  role: z.enum(["admin", "user"]),
});
const data = schema.parse(rawInput); // throws if invalid

Combine with tRPC for automatic input validation on every procedure.

The Result

When these three tools work together:

  • A database migration updates Prisma types
  • The server code fails to compile if it doesn't handle the new shape
  • The client code fails to compile if it accesses a removed field
  • Runtime validation catches malformed input before it reaches business logic

No runtime surprises. No "but it worked on my machine." No undefined is not a function at 3 AM.