如何让TypeScript的getRoutesForPages返回带前缀的映射类型?
解决TypeScript路由前缀类型生成问题
1. 改造shared.ts的类型与函数
首先新增一个泛型类型来生成带前缀的路由对象类型,然后修改路由生成函数的返回类型,同时修复原函数修改只读对象的问题:
export type ReverseMap<T> = T[keyof T]; // 泛型类型:给原路由对象的每个值添加指定前缀 type PrefixedRoutes<T extends Record<string, string>, Root extends string> = { [K in keyof T]: `/${Root}/${T[K]}`; }; export const getRoutesForPages = <T extends Record<string, string>, const Root extends string>( pages: T, root: Root ): PrefixedRoutes<T, Root> => { // 创建新对象存带前缀的路由,不修改原只读对象 const prefixedRoutes = {} as PrefixedRoutes<T, Root>; for (const key in pages) { if (pages.hasOwnProperty(key)) { prefixedRoutes[key] = `/${root}/${pages[key]}` as const; } } return prefixedRoutes; };
2. 调整admin.ts的调用逻辑
不需要手动指定泛型,TypeScript会自动推导正确的类型:
import { getRoutesForPages, ReverseMap } from './shared'; const ROOT = 'admin'; export const PAGES = { PAGE_1: `p-1`, PAGE_2: `p-2`, } as const; export type Page = ReverseMap<typeof PAGES>; // 自动推导生成带前缀的路由对象,类型完全匹配实际值 const ROUTES = getRoutesForPages(PAGES, ROOT); // 现在Route类型会是 '/admin/p-1' | '/admin/p-2' export type Route = ReverseMap<typeof ROUTES>;
核心要点
PrefixedRoutes映射类型:遍历原对象的每个键,用模板字面量类型把前缀和原路由值拼接成精确的字面量类型,比如/${Root}/${T[K]}会把admin和p-1拼成/admin/p-1。- const类型参数
Root:让传入的root参数保留字面量类型(比如'admin'而不是宽泛的string),这样模板字面量才能生成精确的路径类型。 - 不修改原对象:原
PAGES是as const断言的只读对象,直接修改会触发运行时错误,创建新对象存储结果更安全可靠。
这样修改后,Route类型就能正确生成带前缀的路径联合类型,同时getRoutesForPages可以复用在其他模块,传入不同的root生成对应前缀的路由。
内容的提问来源于stack exchange,提问作者Ewan
相关产品推荐
相关产品推荐

