Register the router and read route data through typed route APIs
Register the router type once with the Register interface, and read params, search params, and loader data through route-specific APIs, such as Route.useParams(), getRouteApi('/path'), or hooks with from.
Implementation
- Declare
Registernext to where the router is created:declare module '@tanstack/react-router' { interface Register { router: ReturnType<typeof getRouter> } }. - In a route file, use the route's own hooks, such as
Route.useParams()andRoute.useLoaderData(). - In a component split from its route, use
getRouteApi('/posts/$postId'). - Pass
fromto generic hooks, such asuseParams({ from: '/posts/$postId' }), when neither of the above is convenient. - Use
strict: falseonly in components shared across routes, such as breadcrumbs, and handle every field as possibly missing. - Navigate with
Linkornavigateusing route paths andparams, not hand-built URL strings, so TypeScript checks them.
Rationale
TanStack Router infers route paths, params, search params, and loader data from the route tree, but global hooks and Link see those types only after the router is registered.
Route-specific APIs return exact types for one route, while strict: false returns a loose union where every field may be missing.
Examples
Application: Registration
Incorrect (counterexample):
export const router = createRouter({ routeTree });
Without registration, Link and navigate accept any to value, so a mistyped route compiles.
Correct:
export const router = createRouter({ routeTree });
declare module '@tanstack/react-router' {
interface Register {
router: typeof router;
}
}
Application: Reading params in a route component
Incorrect (counterexample):
function PostDetail() {
const params = useParams({ strict: false });
return <Post id={params.postId!} />;
}
postId is typed as possibly missing, so the component needs a non-null assertion that hides real mistakes.
Correct:
const postRoute = getRouteApi('/posts/$postId');
function PostDetail() {
const { postId } = postRoute.useParams();
return <Post id={postId} />;
}
Validation
Run the type checker and check that a navigation to a nonexistent route or with missing params fails to compile.
Search route-specific components for strict: false and non-null assertions on params.
strict: false in a component genuinely shared across routes is not a violation.