DEV Community

Alex Spinov
Alex Spinov

Posted on

TanStack Router Has Free Type-Safe Routing — Here's How to Use It

React Router works. But if you've ever had a broken link in production because of a typo in a route string, you know the pain. TanStack Router catches those errors at compile time.

What Is TanStack Router?

TanStack Router is a fully type-safe router for React. Every route, every parameter, every search param — validated at compile time. If it compiles, it routes correctly.

Quick Start

npm install @tanstack/react-router
Enter fullscreen mode Exit fullscreen mode
// Define routes with full type safety
import { createRootRoute, createRoute, createRouter } from '@tanstack/react-router';

const rootRoute = createRootRoute({
  component: RootLayout,
});

const indexRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/',
  component: HomePage,
});

const userRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/users/$userId',
  component: UserPage,
  // Validate params at the type level
  parseParams: (params) => ({
    userId: Number(params.userId),
  }),
});

const router = createRouter({
  routeTree: rootRoute.addChildren([indexRoute, userRoute]),
});
Enter fullscreen mode Exit fullscreen mode

Type-Safe Links

// This COMPILES — route exists, params correct
<Link to="/users/$userId" params={{ userId: 123 }}>
  View User
</Link>

// This FAILS at compile time — route doesn't exist
<Link to="/uusers/$userId" params={{ userId: 123 }}>
  View User
</Link>
// TS Error: Type '"/uusers/$userId"' is not assignable

// This FAILS — missing required param
<Link to="/users/$userId">
  View User
</Link>
// TS Error: Property 'userId' is missing
Enter fullscreen mode Exit fullscreen mode

Search Params (Type-Safe)

const productsRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/products',
  validateSearch: (search) => ({
    page: Number(search.page) || 1,
    category: search.category as string || 'all',
    sort: (search.sort as 'price' | 'name') || 'name',
  }),
  component: ProductsPage,
});

function ProductsPage() {
  // search is fully typed: { page: number, category: string, sort: 'price' | 'name' }
  const { page, category, sort } = productsRoute.useSearch();

  return <ProductList page={page} category={category} sort={sort} />;
}
Enter fullscreen mode Exit fullscreen mode

Data Loading

const userRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: '/users/$userId',
  loader: async ({ params }) => {
    // params.userId is typed as number
    return fetchUser(params.userId);
  },
  component: UserPage,
});

function UserPage() {
  const user = userRoute.useLoaderData(); // Fully typed
  return <h1>{user.name}</h1>;
}
Enter fullscreen mode Exit fullscreen mode

Why TanStack Router Over React Router

Feature TanStack Router React Router
Type-safe links Compile-time Runtime strings
Search params Validated + typed Manual parsing
Route params Typed + parsed String only
Devtools Built-in Community
Data loading Integrated Loader pattern
Preloading Hover intent Manual

Key Features

  • 100% type-safe — routes, params, search params, loader data
  • Built-in devtools — inspect route tree, params, cache
  • Preloading — prefetch data on hover
  • Pending states — loading indicators per route
  • Error boundaries — per-route error handling
  • SSR support — server-side rendering compatible

Get Started


Building a data-driven React app? My Apify scrapers provide structured web data via API. Custom solutions: spinov001@gmail.com

Top comments (0)