如何将路由生成函数转为带递归模板字面量的泛型函数?
实现返回字符串字面量的递归路由生成泛型函数
需要将现有的递归路由生成函数改造为泛型函数,使其返回字符串字面量类型而非宽泛的string类型,让类型系统能精确推导出生成的路由路径,比如login的类型应为{ path: '/auth/login', backPath: '/auth' }。
当前实现代码
interface CreateRouteParams { path: string; dependsOn?: CreateRouteParams; } const createRoute = ({ path, dependsOn }: CreateRouteParams): { path: string; backPath?: string } => { if (!dependsOn) return { path }; const parent = createRoute(dependsOn); // 避免开头出现连续两个斜杠 if (parent.path === '/') { return { path: `${parent.path}${path}`, backPath: `${dependsOn.path}` }; } return { path: `${parent.path}/${path}`, backPath: `${dependsOn.path}` }; }; // 使用示例 const root = { path: '/', }; const auth = createRoute({ path: 'auth', dependsOn: root, }); const login = createRoute({ path: 'login', dependsOn: auth, });
改造方案
通过递归模板字面量和泛型类型约束,让TypeScript精确推导路径字面量:
// 递归计算完整路由路径的类型工具 type ResolvePath<Path extends string, ParentPath extends string> = ParentPath extends '/' ? `${ParentPath}${Path}` : `${ParentPath}/${Path}`; // 定义路由结果的泛型类型,递归推导backPath type RouteResult<Path extends string, Deps extends RouteResult<any, any> | undefined> = Deps extends RouteResult<infer ParentPath, infer _> ? { path: ResolvePath<Path, ParentPath>, backPath: ParentPath } : { path: Path }; // 改造后的泛型路由生成函数 function createRoute<Path extends string, Deps extends RouteResult<any, any> | undefined>( params: { path: Path; dependsOn?: Deps } ): RouteResult<Path, Deps> { const { path, dependsOn } = params; if (!dependsOn) return { path } as RouteResult<Path, Deps>; const parent = createRoute(dependsOn); let fullPath: string; if (parent.path === '/') { fullPath = `${parent.path}${path}`; } else { fullPath = `${parent.path}/${path}`; } return { path: fullPath, backPath: parent.path } as RouteResult<Path, Deps>; } // 使用示例,类型推导完全符合预期 const root = createRoute({ path: '/' }); const auth = createRoute({ path: 'auth', dependsOn: root }); const login = createRoute({ path: 'login', dependsOn: auth }); // hover查看login类型:{ path: "/auth/login", backPath: "/auth" }
关键说明
ResolvePath类型:处理父路径与子路径的拼接逻辑,避免根路径后出现重复斜杠。RouteResult泛型:通过条件递归,从依赖的路由结果中提取父路径字面量,生成精确的返回类型。- 泛型函数约束:用
Path extends string捕获传入的路径字面量,Deps约束为已生成的路由结果类型,确保类型推导的准确性。
代码优化建议
- 路径合法性校验:添加类型约束,禁止子路径以斜杠开头(如
path: '/login'),避免生成无效路径:type ValidSubPath = string extends `${infer _}/` ? never : string; // 修改函数参数的path类型为Path extends ValidSubPath - 根路径单独处理:可以专门定义
createRootRoute函数,简化根路径的创建,同时强化类型约束。 - 类型工具复用:将路径处理相关的类型工具抽离到单独的类型模块,方便其他地方复用。
内容的提问来源于stack exchange,提问作者Vishal
相关产品推荐
相关产品推荐

