为何TypeScript递归函数会报扩展参数相关警告?如何解决
TypeScript递归函数参数展开错误分析与修复
原函数代码
const checkNested = ((obj: any, attr: string, ...rest: any[]): boolean => { if (obj === undefined || obj === null) return false if (rest.length === 0 && obj.hasOwnProperty(attr)) return true return checkNested(obj[attr], ...rest) })
错误提示
A spread argument must either have a tuple type or be passed to a rest parameter.
翻译:展开参数必须是元组类型,或者传递给剩余参数
错误含义
这个错误是TypeScript类型检查的规则限制:当使用...语法展开数组作为函数参数时,TypeScript要求该数组要么是元组类型(长度和元素类型完全明确的数组),要么是被传递给函数的剩余参数(即定义为...参数名的形参)。
原代码中,rest被定义为any[](任意类型的数组),递归调用checkNested时,函数的第二个参数要求是string类型,但TypeScript无法确认rest的第一个元素是string,也无法保证rest的长度匹配函数参数的要求,因此触发类型检查错误。
修复方案
方案一:使用函数重载明确参数类型
通过重载定义不同参数长度的类型约束,让TypeScript能正确推断展开后的参数类型:
// 重载:仅检查最后一个属性的情况 function checkNested(obj: any, attr: string): boolean; // 重载:还有后续属性需要检查的情况 function checkNested(obj: any, attr: string, ...rest: [string, ...string[]]): boolean; // 函数实现 function checkNested(obj: any, attr: string, ...rest: string[]): boolean { if (obj === undefined || obj === null) return false; if (rest.length === 0 && obj.hasOwnProperty(attr)) return true; return checkNested(obj[attr], ...rest); }
这里用[string, ...string[]]这个剩余元组类型,确保rest至少包含一个字符串,递归展开后能匹配函数的参数要求。
方案二:统一使用剩余参数接收属性
把所有要检查的属性都放到剩余参数中,递归时传递剩余的属性数组:
const checkNested = ((obj: any, ...attrs: string[]): boolean => { if (obj === undefined || obj === null) return false; const [currentAttr, ...restAttrs] = attrs; if (restAttrs.length === 0 && obj.hasOwnProperty(currentAttr)) return true; return checkNested(obj[currentAttr], ...restAttrs); })
这种方式下,restAttrs是string[]类型,展开后传递给函数的...attrs剩余参数,完全符合TypeScript的类型规则,错误会自动消除。
内容的提问来源于stack exchange,提问作者t56k
相关产品推荐
相关产品推荐

