You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've been using TanStack Router in a large-scale project. While I love the type safety of the generated strings, my team prefers using a centralized ROUTES constant object (e.g., ROUTES.LOGIN) rather than repeating string literals throughout the app.
The challenge with a manual constants file is that it usually isn't type-safe—if you rename a file or add a new route, the constants file drifts from the actual router definition.
I implemented a TypeScript solution that utilizes RegisteredRouter["routesByPath"] to create an exhaustive check. It throws a compile-time error if my ROUTES constant is missing any route defined in the router.
I thought this might be useful for others looking for a "Named Routes" pattern, or perhaps spark a discussion on if a similar mapping could be auto-generated.
Why this is useful:
Allows usage of ROUTES.NAME intellisense throughout the app.
Prevents the constants file from becoming stale.
Leverages the existing type generation without needing a secondary codegen step.
Has anyone else implemented a similar pattern, or is there a recommended way to handle "Named Routes" aliases in TanStack Router?
// 1. Get all valid paths from the router
type AppPath = keyof RegisteredRouter["routesByPath"];
// 2. Define your constants
export const ROUTES = {
LOGIN: "/login",
REGISTER: "/register",
DASHBOARD: "/dashboard",
// ...
} as const satisfies Record<string, AppPath>;
// 3. Utility types to check coverage
type RoutesValues = (typeof ROUTES)[keyof typeof ROUTES];
type MissingRoutes = Exclude<AppPath, RoutesValues>;
// 4. The Exhaustiveness Check
// If 'MissingRoutes' is not never, this type resolves to an error object,
// causing a build failure at the const below.
type AssertAllRoutesAreDefined = MissingRoutes extends never
? true
: {
error: `Some routes are missing in ROUTES constant: ${MissingRoutes}`;
};
// This will error if you add a new file but forget to add it to ROUTES
export const _exhaustiveCheck: AssertAllRoutesAreDefined = true; ```
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
I've been using TanStack Router in a large-scale project. While I love the type safety of the generated strings, my team prefers using a centralized ROUTES constant object (e.g., ROUTES.LOGIN) rather than repeating string literals throughout the app.
The challenge with a manual constants file is that it usually isn't type-safe—if you rename a file or add a new route, the constants file drifts from the actual router definition.
I implemented a TypeScript solution that utilizes RegisteredRouter["routesByPath"] to create an exhaustive check. It throws a compile-time error if my ROUTES constant is missing any route defined in the router.
I thought this might be useful for others looking for a "Named Routes" pattern, or perhaps spark a discussion on if a similar mapping could be auto-generated.
Why this is useful:
Allows usage of ROUTES.NAME intellisense throughout the app.
Prevents the constants file from becoming stale.
Leverages the existing type generation without needing a secondary codegen step.
Has anyone else implemented a similar pattern, or is there a recommended way to handle "Named Routes" aliases in TanStack Router?
Beta Was this translation helpful? Give feedback.
All reactions