TS wrapper函数报number[]无法赋值给[number]错误 不修改结构如何修复
问题复现
现有wrapper函数接收两个入参:被包装的目标函数、参数生成器函数,原代码如下:
function wrapper<K extends Array<any>, T>(fn: (...args: K) => T, pd: (...args: any) => K): T { return fn(...pd()); } wrapper((id: number) => id, (id: number) => { return [id]; })
调用时代码抛出如下类型错误:
Argument of type '(id: number) => number[]' is not assignable to parameter of type '(...args: any) => [id: number]'.
Type 'number[]' is not assignable to type '[id: number]'.
Target requires 1 element(s) but source may have fewer.(2345)
错误原因
类型不匹配的核心是TypeScript的默认类型推断规则:当在参数生成器里直接返回[id]时,TS会默认将其推断为长度不固定的普通数组类型number[];但传入第一个目标函数(id: number) => id时,泛型K已经被推断为固定长度为1、首元素为number的元组类型[id: number]。普通数组无法保证长度一定符合元组的固定长度要求,因此抛出类型错误。
修复方法
不需要改动wrapper函数的入参结构,可按需选择以下方案:
- 方案1:调用侧给返回数组加
const断言const断言会让TS将数组字面量推断为固定长度的只读元组,直接匹配类型要求,改动最小:wrapper((id: number) => id, (id: number) => { return [id] as const; }) - 方案2:调用侧显式标注参数生成器的返回值类型
直接明确告知TS该函数返回对应结构的元组,避免默认推断为普通数组:wrapper((id: number) => id, (id: number): [number] => { return [id]; }) - 方案3:仅调整wrapper的泛型约束,调用侧完全不用改
通过可变元组语法诱导TS在推断参数生成器返回值时优先匹配元组结构,不改变原有函数的入参规则和运行逻辑:function wrapper<K extends any[], T>( fn: (...args: K) => T, pd: (...args: any) => readonly [...K] ): T { return fn(...pd() as K); } // 原调用代码无需任何修改即可通过类型校验 wrapper((id: number) => id, (id: number) => { return [id]; })
内容的提问来源于stack exchange,提问作者Night12138
相关产品推荐
相关产品推荐

