Fastify-Typed Routes With Generics
TypeScript Setup
Fastify ships first-class TypeScript types; route generics give you typed body, params, query, and reply with zero extra build steps.
What you'll learn
- Install Node and Fastify type packages
- Use route generics for typed inputs
- Pair with TypeBox or zod for runtime types
Fastify is written in TypeScript and exposes rich types. The default DX is good — adding a type provider makes it great.
Project Setup
npm i fastify
npm i -D typescript tsx @types/node
npx tsc --init --module nodenext --target es2022 --strict Fastify 5 is ESM-first; set "type": "module" in package.json and use the nodenext module
resolution in tsconfig.json.
Route Generics
type SearchQuery = { q: string; page?: number };
type SearchReply = { results: Array<{ id: number; title: string }> };
app.get<{ Querystring: SearchQuery; Reply: SearchReply }>(
'/search',
async (req) => {
const q = req.query.q.trim();
const page = req.query.page ?? 1;
return { results: await search(q, page) };
},
); req.query, req.body, req.params, and the return type are all checked at compile time.
Type Providers
Hand-written generics drift from runtime schemas. A type provider derives types from your schema:
import { Type } from '@sinclair/typebox';
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
const typed = app.withTypeProvider<TypeBoxTypeProvider>();
typed.post('/users', {
schema: {
body: Type.Object({ email: Type.String({ format: 'email' }) }),
},
handler: async (req) => req.body.email.toLowerCase(),
}); One schema definition powers Ajv validation, OpenAPI docs, and compile-time types — covered in depth in the TypeBox lesson.
Schemas — Validate & Serialize →