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

如何将路由生成函数转为带递归模板字面量的泛型函数?

实现返回字符串字面量的递归路由生成泛型函数

需要将现有的递归路由生成函数改造为泛型函数,使其返回字符串字面量类型而非宽泛的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" }

关键说明

  1. ResolvePath类型:处理父路径与子路径的拼接逻辑,避免根路径后出现重复斜杠。
  2. RouteResult泛型:通过条件递归,从依赖的路由结果中提取父路径字面量,生成精确的返回类型。
  3. 泛型函数约束:用Path extends string捕获传入的路径字面量,Deps约束为已生成的路由结果类型,确保类型推导的准确性。

代码优化建议

  • 路径合法性校验:添加类型约束,禁止子路径以斜杠开头(如path: '/login'),避免生成无效路径:
    type ValidSubPath = string extends `${infer _}/` ? never : string;
    // 修改函数参数的path类型为Path extends ValidSubPath
    
  • 根路径单独处理:可以专门定义createRootRoute函数,简化根路径的创建,同时强化类型约束。
  • 类型工具复用:将路径处理相关的类型工具抽离到单独的类型模块,方便其他地方复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:45:15