TypeScript如何从数组中提取tuple类型?两泛型函数返回类型差异原因?
问题解答
一、两个函数返回类型不同的原因
该差异由TypeScript默认的类型推导策略直接导致:
- 对于
makeTupleByArgs的剩余参数(...items):TS处理多个独立传入的字面量参数时,会默认将泛型T推导为固定长度、固定位置类型的元组类型。因为剩余参数的每个入参是独立的字面量,TS默认你不会后续修改返回值的长度和对应位置的类型,因此推导结果为[number, number, string]。 - 对于
makeTupleByArray的数组参数:TS对直接传入的数组字面量[1, 3, "ABC"]的默认推导规则是「可变数组」,也就是默认你会后续对这个数组做增删、修改元素的操作,因此只会提取所有元素的联合类型,推导为(string | number)[],不会保留长度和位置对应的类型信息。
二、从数组参数生成/提取tuple类型的实现方法
常用有三种实现方案:
方案1:使用const泛型(TS 5.0+支持)
给泛型添加const修饰符,让TS按照字面量常量的规则推导数组,保留元组信息:
function makeTupleByArray<const T extends Array<any>>(items: T) { return items; } const b = makeTupleByArray([1, 3, "ABC"]); // 推导结果为readonly [1, 3, "ABC"],如果要去掉只读属性可以通过类型映射处理
方案2:传入数组时添加as const断言
手动告诉TS这个数组是常量不可变,强制推导为元组:
const b = makeTupleByArray([1, 3, "ABC"] as const); // 推导结果为readonly [1, 3, "ABC"]
方案3:使用可变元组约束(TS 4.0+支持)
如果需要兼容旧版本TS,也可以通过泛型约束明确要求传入元组:
function makeTupleByArray<T extends [...any[]]>(items: T) { return items; } // 调用时显式标注元组类型即可 const b = makeTupleByArray([1, 3, "ABC"] as [number, number, string]); // 推导结果为[number, number, string]
内容的提问来源于stack exchange,提问作者Lunuy
相关产品推荐
相关产品推荐

