TypeScript函数同时使用可选参数与剩余参数如何省略undefined占位
TypeScript 可选参数搭配剩余参数的无占位实现方案
TypeScript 语法强制要求剩余参数必须放在参数列表的最后一位,当你在剩余参数前定义普通可选参数时,不传可选参数就必须显式传入undefined占位,要规避这个问题,有两种类型安全的落地方式:
方案1:函数重载(保留原有顺序传参习惯)
如果要保留按位置传参的调用形式,用TypeScript的函数重载特性定义两类传参规则即可,不需要修改调用习惯:
// 重载签名1:只传必填参数 + 剩余参数,跳过可选参数val_b public ThisIsAFunction(val_a: string, ...val_c: string[]): void; // 重载签名2:传必填参数 + 可选参数val_b + 剩余参数 public ThisIsAFunction(val_a: string, val_b: string, ...val_c: string[]): void; // 函数实际实现,内部做参数拆分 public ThisIsAFunction(val_a: string, val_bOrFirstC?: string, ...restC: string[]) { let val_b: string | undefined; let val_c: string[]; // 这里加判断逻辑区分第二个参数属于val_b还是val_c // 优先用业务规则判断:比如val_b必须匹配特定正则、属于固定枚举值、长度固定等,判断准确率最高 if (val_bOrFirstC && /* 你的val_b匹配规则 */ true) { val_b = val_bOrFirstC; val_c = restC; } else { val_b = undefined; val_c = val_bOrFirstC ? [val_bOrFirstC, ...restC] : restC; } // 后续业务逻辑直接使用val_a、val_b、val_c三个变量即可 }
写完重载后,两种调用方式都可以正常通过类型校验,不需要传undefined占位:
// 不传val_b,直接传剩余参数 ThisIsAFunction("Test", "Test_one", "Test_two", "Test_three"); // 传val_b后再传剩余参数 ThisIsAFunction("Test", "自定义val_b内容", "Test_one", "Test_two");
注意:如果val_b和val_c内的元素完全没有可区分的特征(比如二者都是任意格式字符串,没有任何业务规则差异),重载会存在参数歧义,无法准确判断第二个参数的归属,这种场景更推荐用下一种方案。
方案2:对象参数解构(零歧义,可维护性更强)
把所有参数收敛到一个配置对象中,用解构的方式拿参数,从根源上消除位置传参的歧义,后续新增、调整参数也不需要修改参数顺序:
// 定义参数类型 interface ThisIsAFunctionParams { val_a: string; val_b?: string; val_c?: string[]; } public ThisIsAFunction({ val_a, val_b, val_c = [] }: ThisIsAFunctionParams) { // 直接拿到拆分好的参数使用,不需要额外做参数判断 }
调用时不需要考虑参数顺序,不传val_b也不需要占位:
// 不传val_b的场景 ThisIsAFunction({ val_a: "Test", val_c: ["Test_one", "Test_two", "Test_three"] }); // 传val_b的场景 ThisIsAFunction({ val_a: "Test", val_b: "自定义val_b内容", val_c: ["Test_one"] });
这种写法适合参数数量较多、后续迭代频繁的函数,类型提示清晰,传参时不容易出错。
不推荐直接用
arguments对象做隐式参数截取,这类写法会丢失TypeScript的静态类型校验能力,编译阶段无法发现传参类型、数量错误,线上隐患较大。
内容的提问来源于stack exchange,提问作者Cptain_Whitebeard
相关产品推荐
相关产品推荐

