Schema Validation
Validate and transform route params with Standard Schema
Schema Validation
Routes supports Standard Schema for runtime validation and transformation of route parameters.
Basic Usage
Pass a config with params to createRoutes to enable validation:
import { createRoutes } from "@jlnstack/routes"
import { z } from "zod"
type AppRoutes = "/users/[id]"
const routes = createRoutes<AppRoutes>()({
"/users/[id]": {
params: { id: z.coerce.number() },
},
})
routes.users.id.getRoute({ id: 42 })
// => "/users/42"The schema's output type is automatically inferred — id expects a number, not a string.
Supported Libraries
Any library implementing the Standard Schema spec works:
Multiple Params
Define schemas for multiple parameters:
type AppRoutes = "/users/[id]/posts/[postId]"
const routes = createRoutes<AppRoutes>()({
"/users/[id]/posts/[postId]": {
params: {
id: z.coerce.number(),
postId: z.string().uuid(),
},
},
})
routes.users.id.posts.postId.getRoute({
id: 123,
postId: "550e8400-e29b-41d4-a716-446655440000",
})
// => "/users/123/posts/550e8400-e29b-41d4-a716-446655440000"Partial Schema Coverage
You don't need schemas for every param. Unspecified params default to string:
type AppRoutes = "/users/[id]" | "/blog/[slug]"
const routes = createRoutes<AppRoutes>()({
"/users/[id]": { params: { id: z.coerce.number() } },
})
routes.users.id.getRoute({ id: 42 }) // id: number
routes.blog.slug.getRoute({ slug: "post" }) // slug: stringValidation Errors
When validation fails, an error is thrown with details:
type AppRoutes = "/users/[id]"
const routes = createRoutes<AppRoutes>()({
"/users/[id]": {
params: { id: z.number().positive() },
},
})
routes.users.id.getRoute({ id: -1 })
// throws: Validation failed for param "id": Number must be greater than 0Limitations
- Async validation is not supported — schemas must validate synchronously
- Route patterns are inferred from schema map keys when no explicit generic is provided