router type safety

[check: …]
📖 Read the full guide — end-to-end type-safe routing, types flowing out of the route definition to every touchpoint. This page is the interactive companion.

The one idea

TanStack Router's whole point: the route DEFINITION is the single source of truth, and types flow OUT of it to every navigation, param read, and loader — no stringly-typed paths.

You define a route once (path params + validated search params + loader return + context). The router infers all of it and pipes those types through the entire routing experience. Every <Link>, navigate(), useParams(), useSearch() and loader is then checked against that definition at compile time. Contrast: react-router hands you Record<string, string | undefined> and lets <Link to> be any string — valid URL or not.

route def = source of truth types inferred, not hand-written route-tree codegen powers it rename a param → breaks everywhere, at compile time

The type-flow — types flow OUT of the route definition

One route definition below. Five touchpoints read from it — and each one is typed by inference, no angle brackets, no as any. The generated route tree is what lets the router know all routes in advance, which is the prerequisite for any of this.

the route definition — the single source of truth
// routes/users.$userId.tsx — file-based routing generates the route tree
export const Route = createFileRoute('/users/$userId')({
  // search params: validated → typed (standard schema)
  validateSearch: (search) => ({
    page: Number(search.page ?? 1),     // page: number
    filter: String(search.filter ?? ''), // filter: string
  }),
  // loader: params + search are typed IN; the return type flows OUT
  loader: ({ params, search }) => fetchUser(params.userId, search.page),
  component: UserComponent,
})
▼ types inferred & piped through to every touchpoint ▼

Type-check simulation — flip a param, watch it fail

A deterministic mock of what the TypeScript compiler does. Pick what the developer writes into <Link> / navigate(), then run the type-check. Correct input → PASS; a wrong param type, a missing search key, or an unknown route → a simulated TS error + FAIL. The gold-check above pins: correct → pass, wrong → fail, and exactly 5 touchpoints.

— pick a scenario above —
Pick a scenario, then hit run type-check.

Typed touchpoints — TanStack vs react-router

Same six touchpoints, two routers. react-router's useParams returns Record<string, string | undefined> and its <Link to> accepts any string — there's no route tree to check against.

This bundle is TanStack Router's core thesis — end-to-end type-safe routing — the foundation TanStack Start is built on. Cross-refs: 🔗 tanstack_start_overview (Start inherits all of this) · 🔗 metaframework_landscape.