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

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,提问作者고민영

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:42:45