TypeScript中能否用const类型参数捕获可变参数?
TypeScript 5.0 const类型参数能否捕获可变参数?
TypeScript 5.0 引入了const类型参数,能否通过这类类型参数捕获可变参数的具体类型?
以下是尝试实现的函数:
function insertIf<const V extends any[]>(condition: boolean, ...value: V): V | readonly [] { if (condition) { return value; } else { return []; } }
但问题在于,无论传入什么实际参数,返回类型始终被推导为any[] | readonly [],无法捕获参数的具体类型。比如调用insertIf(true, { s: 'a' }, { s: '?'})时,返回类型并没有体现出传入的两个对象的结构。
解决方法
问题出在类型约束V extends any[]上——这个约束会让TypeScript将V推导为宽泛的数组类型而非精确的元组类型,导致const类型参数无法发挥作用。我们需要调整类型约束,让TypeScript推导元组类型:
function insertIf<const V extends readonly any[]>(condition: boolean, ...value: V): V | readonly [] { if (condition) { return value; } else { return []; } }
或者更简洁地省略数组约束,让TypeScript自动推导元组:
function insertIf<const V>(condition: boolean, ...value: V): V extends readonly any[] ? V | readonly [] : never { if (condition) { return value as any; } else { return [] as any; } }
此时调用insertIf(true, { s: 'a' }, { s: '?'}),返回类型会被精确推导为readonly [{ s: 'a' }, { s: '?' }] | readonly [],成功捕获了可变参数的具体类型和长度。
原理说明
const类型参数的作用是让TypeScript将传入的字面量参数推导为不可变的精确类型(比如元组而非数组、字面量类型而非宽泛的基础类型)。但如果给V加上extends any[]的约束,TypeScript会优先将其推导为数组类型,忽略const参数的元组推导行为。改成readonly any[]或者不指定数组约束,才能让const参数触发元组类型的精确推导。
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

