03. Router:类型安全不是装饰

TanStack Router 的“强”不只是文件路由,而是整个 route tree 被 TypeScript 认识。

route tree 心智模型

Next.js 的文件系统本身就是框架入口;TanStack Router 的文件路由会生成 route tree,但你仍然显式创建 router、传 context、挂 provider。文件只是生成配置的方式,不是上帝。

// main.tsx
const router = createRouter({
  routeTree,
  context: { queryClient },
})

ReactDOM.createRoot(root).render(
  <RouterProvider router={router} />
)

文件路由示例

// src/routes/posts.$postId.tsx
export const Route = createFileRoute('/posts/$postId')({
  loader: ({ params }) => fetchPost(params.postId),
  component: PostPage,
})

function PostPage() {
  const post = Route.useLoaderData()
  return <article>{post.title}</article>
}

类型安全导航

TanStack 的 Link 知道哪些 route 存在、需要哪些 params/search。路径拼错不是运行时 404,而是编译期噪音。编译器偶尔像一个烦人的同事,但这次它是对的。

<Link to="/posts/$postId" params={{ postId: post.id }}>
  Open
</Link>

// 如果漏掉 postId,或者写成 /post/$id,TypeScript 应该抱怨。

布局与 pathless routes

TanStack 支持 nested routes、layout routes 和 pathless layouts。和 Next 的 layout.tsx 类似,但 route context、beforeLoad、loader 都可以参与父子继承。

概念TanStack 意义Next.js 对照
Nested route父子路由匹配与 Outlet嵌套路由 segment
Pathless layout不增加 URL 段,只共享布局/逻辑route group / layout 近似
Route context父路由向子路由传 typed contextlayout/provider,但更路由生命周期化
练习:想一个后台管理系统:/dashboard 需要 auth,所有子页面都需要 user 和 permissions。TanStack 中你应把 auth 检查放在父 route 的 beforeLoad,而不是每个页面复制。复制粘贴是弱智版继承。
快速判断

TanStack 文件路由生成 route tree 后,开发者是否还完全失去控制?