TypeScript模板字面量类型可构建强类型异步路由体系,统一路径结构、参数类型与加载时机,实现客户端跳转、服务端预取和参数校验的类型共享与自动推导。
用 TypeScript 模板字面量类型构建异步路由参数的强类型约束体系,核心是把“路径结构 + 参数类型 + 异步加载时机”三者在类型层面耦合起来,让参数校验、跳转调用、服务端预取(如 Next.js 的 generateStaticParams 或 getServerSideProps)全部共享同一套类型定义,避免运行时解析错误或漏传字段。
异步路由常含动态段(如 /post/[id])、可选段(如 /user/[id]/[tab?])或嵌套路由组(如 /admin/[...rest])。模板字面量可逐层建模这些语义:
string 或更窄类型占位,如 type PostId = `${number}`(强制数字字符串)或 type Slug = `a-${string}-z`(带固定前缀后缀)type TabSegment = '' | `/[tab]`,再组合进完整路径:type UserRoute = `/user/[id]${TabSegment}`
[...rest] 行为,例如 type RestPath = `${string}/${RestPath}` | `${string}`,再约束为合法子集:type AdminSubpath = 'dashboard' | 'settings' | 'logs'; type AdminRoute = `/admin/${AdminSubpath}` | `/admin/${RestPath & `${AdminSubpath}/${string}`}`
仅定义路径类型不够,关键是要让 generateStaticParams、getServerSideProps 或自定义 load() 函数能根据路径字面量自动获得参数结构和返回类型:
infer 提取参数名与类型:type ExtractParams<P> = P extends <code>`/${infer First}/${infer Rest}` ? { [K in First]: string } & ExtractParams<`/${Rest}`> : {};id 映射为 number,slug 映射为 string
type RouteLoader<P> = (params: ExtractParams<P>) => Promise<{ data: any; meta?: object }>;/post/[id] 的 loader 必须接收 { id: string },而 /user/[uid]/[lang?] 的 loader 接收 { uid: string; lang?: string }
generateStaticParams 的返回值类型设为 Array<ExtractParams<AppRoute>>,TS 会检查你返回的对象是否覆盖所有必需字段,且值类型匹配异步路由的痛点常在于客户端导航(如 router.push())和服务端生成(如 generateStaticParams)使用两套参数逻辑。模板字面量可桥接二者:
function navigateTo<P extends AppRoute>(path: P, params: ExtractParams<P>): void { ... }navigateTo('/post/[id]', { id: '123' }) 合法,但 navigateTo('/post/[id]', { id: 123 }) 报错(类型不匹配),navigateTo('/post/[id]', {}) 也报错(漏传)export async function generateStaticParams() { return [{ id: '1' }, { id: '2' }] satisfies Array<ExtractParams<'/post/[id]'>; }satisfies 确保数组结构符合预期,又保留字面量精度供 IDE 补全/[lang]/post/[id]),可扩展为:type LocalizedRoute = `${LangPrefix}${AppRoute}`,再用嵌套 ExtractParams 分离 lang 和业务参数最终要落地,需把类型系统和框架机制对齐:
AppRoute 类型用于 RouteSegmentConfig 的 path 字段,并在 layout/server component 中用 useSelectedLayoutSegment() 的返回值做类型守卫TypedNavigate Hook,其参数签名由传入的路径字符串 infer 出来,同时支持 loader 配置项的类型自动关联if (!params.id || !/^d+$/.test(params.id)) throw new Error('Invalid post ID'),防止恶意构造 URL 绕过编译检查