One type alias derived from the router’s generated output. Every nav config, tab mapping, crosslink, and URL-generating utility is typed against the real route tree. Rename or delete a route and every stale reference becomes a compile error.

The alias

// routePaths.ts
export type RoutePath = FileRouteTypes["to"];

FileRouteTypes is populated by TanStack Router’s code generator via module augmentation on @tanstack/react-router. Run the generator; the type updates. No maintenance required.

The resulting union looks like:

type RoutePath =
  | "/orders"
  | "/orders/$orderId"
  | "/orders/$orderId/returns"
  | "/customers/accounts/$customerId"
  | "/invoices"
  | ... // every registered route

Usage

Use RoutePath anywhere a route path string appears:

// Nav config
type NavItem = { label: string; path: RoutePath };

// Tab route mapping
const TABS: Record<string, RoutePath> = {
  overview:  "/customers/accounts/$customerId",
  orders:    "/customers/accounts/$customerId/orders",
};

// Crosslink helpers
function buildLink(to: RoutePath, params: Record<string, string>): string { ... }

When /customers/accounts/$customerId is renamed to /customers/$customerId, every NavItem, tab mapping, and crosslink that referenced the old string fails at tsc, not at runtime.

Exemptions

Fields that point outside the SPA (legacy app routes, third-party URLs) use string explicitly and are annotated:

type NavItem = {
  path:       RoutePath;  // SPA route, enforced
  legacyPath: string;        // legacy app, exempt
};

<Link to> is enforced at the component boundary. RoutePath enforces the shape in data structures — nav arrays, lookup maps, utility functions — that don’t go through a JSX element. Both are necessary; they cover different surfaces.