TypeScript中为何无法推断函数参数中的只读元组类型?
TypeScript中Readonly元组联合作为剩余参数的类型推断问题
先看几个测试用例:
type Test1 = Parameters<(...args: [string] | [number]) => void>; // Test1 is [string] | [number] 符合预期 type Test2 = Parameters<(...args: Readonly<[string] | [number]>) => void>; // Test2 is never 出现异常结果
简化后的对比示例:
type Test3 = ((...args: Readonly<[string] | [number]>) => void) extends (...args: infer P) => any ? true : false; // Test3 is false type Test4 = ((...args: Readonly<[string] | [number]>) => void) extends (...args: any) => any ? true : false; // Test4 is true
原因解析
核心问题在于TypeScript对剩余参数的类型推断有严格规则:
- 剩余参数的类型必须是单一的数组/元组类型(元组属于数组的特殊形式),而
Readonly<[string] | [number]>实际等价于Readonly<[string]> | Readonly<[number]>,是两个只读元组的联合类型,并非单一的数组类型。 Parameters工具类型依赖infer P推断剩余参数类型,而infer在处理剩余参数时,要求被推断的类型必须符合“可展开的数组/元组”约束。联合的只读元组无法满足这个约束——TypeScript无法将两种不同的元组统一推断为一个合法的P,因此推断失败,最终返回never,对应Test2和Test3的结果。- 而
any是TypeScript的顶级类型,任何类型都可以赋值给any,所以Test4会返回true,这和infer P的逻辑完全不同——infer不是简单匹配任意类型,而是要遵循剩余参数的类型规则进行有效推断。
简单来说:infer P不是any的“带存储版”,它在推断剩余参数时必须符合数组/元组的类型要求,而联合的只读元组不满足这个要求,导致推断失败。
内容的提问来源于stack exchange,提问作者cdauth
相关产品推荐
相关产品推荐

