TypeScript中如何将路由参数函数的undefined参数设为可选?
解决TypeScript路由参数函数的可选参数类型问题
要实现无路径参数时无需传入undefined,同时保留有参数时的类型校验,可以通过函数重载或者条件类型结合剩余参数的方式实现,以下是具体方案:
方案一:函数重载
通过定义两个重载签名,分别处理"无参数URL"和"有参数URL"的场景:
const projectDetailUrl = "/project/:id"; const projectUrl = "/project"; export type ExtractParams<T extends string> = T extends `${infer _Start}:${infer Param}/${infer _End}` ? Param | ExtractParams<_End> : T extends `${infer _Start}:${infer LastParam}` ? LastParam : never; export type CreateParamObject<T extends string> = ExtractParams<T> extends never ? undefined : { [K in ExtractParams<T>]: string; }; // 重载1:无参数URL,无需传第二个参数 function push<T extends string>(url: T): CreateParamObject<T> extends undefined ? void : never; // 重载2:有参数URL,必须传对应参数对象 function push<T extends string>(url: T, params: CreateParamObject<T>): void; // 函数实现 function push<T extends string>(url: T, params?: CreateParamObject<T>) { console.log(url); console.log(params); } // 合法调用示例 push(projectUrl); // ✅ 无需传第二个参数 push(projectDetailUrl, { id: "1" }); // ✅ 类型校验通过 // 错误调用示例(会触发TypeScript报错) push(projectDetailUrl); // ❌ 缺少必填参数 push(projectUrl, { id: "1" }); // ❌ 传入了不必要的参数
方案二:条件类型结合剩余参数
利用剩余参数的条件类型约束,让参数列表根据URL是否包含路径参数自动调整:
const projectDetailUrl = "/project/:id"; const projectUrl = "/project"; export type ExtractParams<T extends string> = T extends `${infer _Start}:${infer Param}/${infer _End}` ? Param | ExtractParams<_End> : T extends `${infer _Start}:${infer LastParam}` ? LastParam : never; export type CreateParamObject<T extends string> = ExtractParams<T> extends never ? undefined : { [K in ExtractParams<T>]: string; }; function push<T extends string>( url: T, ...args: CreateParamObject<T> extends undefined ? [] : [CreateParamObject<T>] ) { const params = args[0]; console.log(url); console.log(params); } // 合法调用示例 push(projectUrl); // ✅ 无需传第二个参数 push(projectDetailUrl, { id: "1" }); // ✅ 类型校验通过 // 错误调用示例(会触发TypeScript报错) push(projectDetailUrl); // ❌ 参数数量不足 push(projectUrl, {}); // ❌ 传入了不必要的参数
原理说明
原代码中params是必填参数,因此即使不需要参数也必须传入undefined。通过以下方式优化后:
- 当URL无路径参数时(
ExtractParams<T>返回never),CreateParamObject<T>返回undefined,此时参数列表允许为空; - 当URL有路径参数时,
CreateParamObject<T>返回对应的参数对象类型,此时第二个参数变为必填项,且会进行严格的类型校验。
内容的提问来源于stack exchange,提问作者고민영
相关产品推荐
相关产品推荐

