You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中声明类型安全的任意有效Route数组?

如何在NextJS静态类型化路由中声明类型安全的任意有效Route数组?

TL;DR: 借助NextJS的静态类型化路由,如何声明一个类型安全的任意有效Route数组?


我有一个启用了typedRoutes的NextJS v15(app router)项目,文件结构如下:

src/app/page.tsx
src/app/projects/page.tsx
src/app/projects/[projectId]/page.tsx

这意味着我可以编写如下代码,Next会自动校验路由的有效性:

import Link from 'next/link';

function SomeValidLinks(){
  const projectId = '123';
  return [
    <Link href='/'>Root</Link>,
    <Link href='/projects'>Projects</Link>,
    <Link href={`/projects/${encodeURIComponent(projectId)}`}>Project {projectId}</Link>,
  ];
}

function DoesNotWork(){
  // 类型校验错误:Type "/banana" is not assignable to type 'UrlObject | RouteImpl<"/banana">'.
  return <Link href='/banana'>Invalid route</Link>; 
}

这一特性很实用,但我无法找到声明任意有效Route值数组的方法。例如以下代码:

const routes: Route<string>[] = [];
routes.push('/');                                          // ✅
routes.push('/projects');                                  // ✅
routes.push(`/projects/${encodeURIComponent(projectId)}`); // 💥

动态路由无法赋值给Route<string>,最后一行会报错:Argument of type '/projects/${string}' is not assignable to parameter of type 'Route<string>'.

因此我的核心问题是:如何声明一个包含有效Route的数组?

我尝试过以下无效方案:

  • 将数组声明为Route[],这与Route<string>等价,无法解决问题
  • 将数组声明为Route<any>[],这会破坏类型安全性,等同于any[],可存入错误链接
  • 将数组声明为Route<unknown>[],会报错:Type 'unknown' does not satisfy the constraint 'string'.
  • 尝试类似Java中Route<?>的写法,表示只要是Route<X>即可,不关心X的具体类型,但TypeScript不支持该语法

目前唯一勉强可行的方案是使用泛型和类型推断:

function doSomethingWithRoutes<T extends string>(routes: Route<T>[]) {
  // 处理路由数组
}
doSomethingWithRoutes('/', '/projects', `/projects/${encodeURIComponent(projectId)}`); // ✅
doSomethingWithRoutes('/banana'); // 💥

但这种方式十分冗长繁琐,所有接收路由数组的函数都需要泛型参数化,且无法显式为变量指定类型,因此我并不喜欢这种方案。


更具体的示例:

我的实际场景之一是菜单组件,希望构建一个可接收菜单项数组并渲染菜单的组件,示例如下:

const menu = <NavMenu 
    items={[
      { url: '/',             label: 'Overview' },
      { url: '/projects',     label: 'Projects' },
      { url: '/applications', label: 'Applications' },
      { url: '/me',           label: 'Your profile' },
    ]} 
  />;

为了在url字段中使用类型安全的路由,我必须将组件及其props设置为泛型,这会导致代码重复、可读性下降,并且影响所有使用该组件的代码:

type MenuItem<T extends string> = {
  url: Route<T>;
  label: string;
};

function NavMenu<T extends string>(props: { items: MenuItem<T>[] }) {
  // 渲染菜单
}

如果我在某个地方添加Route属性、参数或字段,所有相关代码都需要改为泛型,这意味着一个小改动可能会影响整个代码库的大量部分。

内容的提问来源于stack exchange,提问作者gustafc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:47:02