如何基于泛型省略或可选化函数的最后一个参数?
基于泛型实现函数最后一个参数的省略/可选化
针对需求,我们可以通过条件类型结合剩余参数或者函数重载两种方式实现,让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
相关产品推荐
相关产品推荐

