如何检测TypeScript元组为有限或无限?
如何检测TypeScript元组是有限还是无限?
我需要实现一个类型工具IsFinite来判断元组是有限还是无限,但当前实现无法处理包含多个rest元素的复杂元组,比如[string, ...[string, number], ...string[], string]会返回never,而非正确的false。
原实现代码
type IsFinite<T extends any[], Finite = true, Infinite = false> = T extends [] ? Finite : T extends (infer Element)[] ? Element[] extends T ? Infinite : T extends [any, ...infer Rest] ? IsFinite<Rest, Finite, Infinite> : never : never type Foo1 = IsFinite<[string]> // true type Foo2 = IsFinite<[]> // true type Foo3 = IsFinite<string[]> // false type Foo4 = IsFinite<[arg1: string, ...args: string[]]> // false type Foo5 = IsFinite<[string, ...[string, number], ...string[], string]> // never <- 无法处理该情况
问题分析
原实现通过递归拆解元组判断有限性,但当元组包含多个rest扩展(比如嵌套的...[string, number]和...string[])时,T extends [any, ...infer Rest]无法匹配这种复杂结构,导致走到never分支。实际上只要元组中存在任意一个无限rest元素(即数组类型而非有限元组),整个元组就是无限的。
解决方案
换个思路:只要元组无法被递归拆解为首元素加剩余元组,就说明它包含无限rest,属于无限元组。以下是修正后的实现:
type IsFinite<T extends any[], Finite = true, Infinite = false> = T extends [] ? Finite : T extends [infer _, ...infer R] ? IsFinite<R, Finite, Infinite> : Infinite;
测试验证
type Foo1 = IsFinite<[string]> // true type Foo2 = IsFinite<[]> // true type Foo3 = IsFinite<string[]> // false type Foo4 = IsFinite<[arg1: string, ...args: string[]]> // false type Foo5 = IsFinite<[string, ...[string, number], ...string[], string]> // false <- 现在正确返回无限
逻辑说明
- 空元组直接判定为有限(
Finite) - 能拆解为首元素加剩余元组的,递归判断剩余部分
- 无法拆解的元组(包含无限rest)直接判定为无限(
Infinite)
这种实现可以处理任意位置、任意数量的rest元素,覆盖所有复杂元组场景。
内容的提问来源于stack exchange,提问作者TrevTheDev
相关产品推荐
相关产品推荐

