如何创建含自定义键与buildUrl方法的TypeScript Route类型?
构造自定义TypeScript Route类型的方案
基础灵活方案
如果只需要允许每个Route实例拥有任意字符串类型的静态属性,搭配自定义的buildUrl方法,你可以使用泛型让类型更贴合每个实例的具体结构:
type Route<T extends Record<string, string> = Record<string, string>> = T & { buildUrl: (params: Record<string, string>) => string; };
使用时,TypeScript可以自动推断静态属性类型,也可以显式指定:
// 自动推断静态属性 const profileRoute = { base: 'profile', param: ':profileId', tab1: 'details', tab2: 'edit', buildUrl: ({ profileId, tab }) => `/profile/${profileId}/${tab}`, } satisfies Route; // 显式指定静态属性类型 type OrderRouteStatic = { base: 'order'; param: ':orderId'; status: 'status'; }; const orderRoute: Route<OrderRouteStatic> = { base: 'order', param: ':orderId', status: 'status', buildUrl: ({ orderId, status }) => `/order/${orderId}/${status}`, };
进阶严格关联方案
如果希望buildUrl的参数类型能和静态属性中的参数占位符(比如:profileId)自动关联,避免参数遗漏或不匹配,可以通过类型提取实现约束:
首先定义参数提取的工具类型:
// 从路径占位符中提取参数名(如":profileId" → "profileId") type ExtractParamName<T extends string> = T extends `:${infer Param}` ? Param : never; // 从Route静态属性中提取所有参数名的联合类型 type GetRouteParams<T extends Record<string, string>> = ExtractParamName<T[keyof T]>;
然后构建严格约束的Route类型:
type StrictRoute<T extends Record<string, string>> = T & { buildUrl: ( params: Record<GetRouteParams<T>, string> & Partial<Record<string, string>> ) => string; };
使用示例:
const strictProfileRoute = { base: 'profile', param: ':profileId', tab1: 'details', buildUrl: ({ profileId, tab }) => `/profile/${profileId}/${tab ?? 'details'}`, } satisfies StrictRoute<typeof strictProfileRoute>; // 调用时必须传入profileId,tab为可选参数 strictProfileRoute.buildUrl({ profileId: '123' }); // ✅ 合法 strictProfileRoute.buildUrl({ profileId: '123', tab: 'edit' }); // ✅ 合法 // strictProfileRoute.buildUrl({}); // ❌ 报错:缺少必填参数profileId
方案选择
- 基础方案适合对参数约束要求不高、需要快速定义Route实例的场景;
- 进阶方案适合需要强类型校验、确保
buildUrl参数与路径占位符匹配的场景。
内容的提问来源于stack exchange,提问作者MarksCode
相关产品推荐
相关产品推荐

