如何让TypeScript支持可选参数?解决多参数函数编译报错
解决TypeScript中可变参数函数的类型报错问题
问题场景
以下JavaScript代码运行正常,但转成TypeScript时出现类型错误:
t.ts:11:34 - error TS2554: Expected 1 arguments, but got 6. 11 console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 2)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ t.ts:14:34 - error TS2554: Expected 1 arguments, but got 6. 14 console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 4)) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
原JS代码如下:
var obj = [{ "category1": { nested: { a: 'string', b: [69, 13, 15] } }, "category2": "2", }]; console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 2)) // 输出 15 console.log(where_undefined(obj, 0, 'category1', 'nested', 'b', 4)) // 输出 undefined at key 4 function where_undefined(obj) { var args = Array.prototype.slice.call(arguments) args.shift(); while (args.length) { var arg = args.shift(); if (obj[arg] === undefined) { console.log("undefined at key " + arg); break; } else { obj = obj[arg]; } } return obj; }
解决方案
方法1:使用剩余参数(推荐)
TypeScript支持剩余参数语法,可接收任意数量的后续参数,同时保证类型检查。改造后的函数如下:
const obj = [{ "category1": { nested: { a: 'string', b: [69, 13, 15] } }, "category2": "2", }]; console.log(whereUndefined(obj, 0, 'category1', 'nested', 'b', 2)) // 输出 15 console.log(whereUndefined(obj, 0, 'category1', 'nested', 'b', 4)) // 输出 undefined at key 4 // 剩余参数 keys 接收任意数量的 string | number 类型参数 function whereUndefined(obj: unknown, ...keys: (string | number)[]) { let current = obj; for (const key of keys) { // 先判断当前值是否为对象/数组,避免访问非索引类型的属性 if (typeof current === 'object' && current !== null) { if (current[key as keyof typeof current] === undefined) { console.log(`undefined at key ${key}`); break; } current = current[key as keyof typeof current]; } else { console.log(`cannot access key ${key} on non-object value`); break; } } return current; }
优化点说明:
- 用
...keys: (string | number)[]声明可变参数,明确告诉TS函数可接收任意数量的字符串或数字类型键名 - 替换
arguments为剩余参数,符合现代JS/TS写法且更类型安全 - 添加类型断言
key as keyof typeof current,解决属性访问的类型报错 - 增加非对象值判断,避免运行时错误
方法2:保留arguments并兼容类型(不推荐)
如果一定要保留arguments用法,可通过以下方式兼容,但会损失部分类型安全性:
// 方式1:用any绕过类型检查(快速但失去TS类型优势) function whereUndefined(obj: any, ...args: any[]) { const keys = Array.prototype.slice.call(arguments); keys.shift(); let current = obj; while (keys.length) { const arg = keys.shift(); if (current[arg] === undefined) { console.log(`undefined at key ${arg}`); break; } else { current = current[arg]; } } return current; } // 方式2:函数重载(适合明确参数数量范围的场景) function whereUndefined(obj: unknown, key1: string | number): unknown; function whereUndefined(obj: unknown, key1: string | number, key2: string | number): unknown; function whereUndefined(obj: unknown, ...keys: (string | number)[]): unknown { // 实现逻辑同方法1 }
报错原因
TypeScript是强类型语言,原JS函数仅声明了一个参数obj,但调用时传入了多个参数,TS类型检查会判定参数不匹配,因此抛出Expected 1 arguments, but got 6错误。通过声明可变参数的类型,让TS识别函数可接收多个参数,即可解决问题。
内容的提问来源于stack exchange,提问作者Sandra Schlichting
相关产品推荐
相关产品推荐

