What are shared types and validation?
A single schema — typically a Zod schema — that defines a data shape once and serves both as the TypeScript type and as the runtime validator, on the client and the server. One definition, used everywhere, for both compile-time types and runtime checks.
Why it matters
Types vanish at runtime, so you still need runtime validation at the boundary; and duplicating the shape in three places (client type, server type, validator) is where drift creeps in. A shared schema collapses all of that into one source of truth, which is the cleanest expression of full-stack type safety.
What to learn
- Deriving a TypeScript type from a Zod schema
- Using one schema for client and server validation
- Placing shared schemas in a common package
- Parsing and narrowing untrusted input
- Composing and reusing schemas
- Transformations and defaults in schemas
- Keeping the schema the single source of truth
Common pitfall
Keeping the validator and the TypeScript type as separate, hand-maintained
definitions. They drift — the validator allows a field the type forbids, or vice
versa — and the guarantees rot. Derive the type from the schema (Zod's infer) so
the validator and the type can never disagree.
Resources
Primary (free):
- Zod — Documentation · docs
- Zod — Type inference · docs
- Total TypeScript — Zod tutorial · course
Practice
Define one Zod schema for a data shape, derive its TypeScript type with infer,
and use the same schema to validate on the server and the client form. Change the
schema and confirm both the type and the validation update from the one edit.
Done when a single schema drives types and validation on both halves.
Outcomes
- Derive a TypeScript type from a Zod schema.
- Validate with one schema on client and server.
- Place shared schemas in a common package.
- Keep one schema as the single source of truth.