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

如何基于泛型省略或可选化函数的最后一个参数?

基于泛型实现函数最后一个参数的省略/可选化

针对需求,我们可以通过条件类型结合剩余参数或者函数重载两种方式实现,让makeRequest的第二个参数根据传入的Method自动调整必填/可选状态:

方案一:条件类型 + 剩余参数(适配Method较多的场景)

先定义辅助类型判断对象所有属性是否均为可选,再通过条件类型动态生成参数列表:

interface Requests {
     post: {
         data: {
             test: number
         }
     }
     patch: {
         data: {
            test?: number
         }
     }
     get: never
 }

// 辅助类型:判断类型的所有属性是否都是可选的
type AllPropertiesOptional<T> = { 
  [K in keyof T]-?: {} extends Pick<T, K> ? true : false 
}[keyof T] extends true ? true : false;

const makeRequest = <Method extends keyof Requests>(
    method: Method,
    ...args: Requests[Method] extends { data: infer Data } 
        ? // 分三种场景处理参数
          Data extends never 
            ? [] // get方法:无需第二个参数
            : AllPropertiesOptional<Data> extends true 
              ? [data?: Data] // patch方法:第二个参数可选
              : [data: Data] // post方法:第二个参数必填
        : []
) => { 
    const data = args[0];
    // 执行请求逻辑
};

测试验证:

makeRequest('post', { test: 1 }); // ✅ 正常(必填第二个参数)
makeRequest('patch'); // ✅ 正常(可省略第二个参数)
makeRequest('patch', { test: 2 }); // ✅ 正常(可传参数)
makeRequest('get'); // ✅ 正常(无第二个参数)

方案二:函数重载(适配Method较少的场景)

通过明确的重载签名直接定义每种Method对应的参数规则,可读性更强:

interface Requests {
     post: {
         data: {
             test: number
         }
     }
     patch: {
         data: {
            test?: number
         }
     }
     get: never
 }

// 重载签名:为每个Method定义参数规则
function makeRequest(method: 'post', data: Requests['post']['data']): void;
function makeRequest(method: 'patch', data?: Requests['patch']['data']): void;
function makeRequest(method: 'get'): void;

// 实现签名:统一处理逻辑
function makeRequest(method: keyof Requests, data?: any) {
    // 执行请求逻辑
};

该方案代码直观,适合Method数量不多的场景,测试效果与方案一一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:35:23