TypeScript中如何定义带最小/最大长度限制的数组类型
实现方案
你的思路完全可行,通过递归生成[start, end]区间内所有长度对应的固定长度元组,再将这些元组类型做联合,即可满足校验需求,完整实现代码如下:
// 辅助类型:构建长度为N的占位元组,用于长度计数 type BuildTuple<N extends number, T = unknown, R extends T[] = []> = R['length'] extends N ? R : BuildTuple<N, T, [...R, T]>; // 核心类型:递归生成元素类型为T、长度在[Start, End]区间的所有元组联合 type RangeTuple< T, Start extends number, End extends number, Current extends T[] = BuildTuple<Start, T>, Result extends T[] = never > = Current['length'] extends End ? Result | Current : RangeTuple<T, Start, End, [...Current, T], Result | Current>; // 对外暴露的目标类型,匹配预期的使用方式 type my_type<T, N extends {start: number, end: number}> = RangeTuple<T, N['start'], N['end']>;
校验效果验证
使用给出的测试用例校验,结果完全符合预期:
var my_arr: my_type<number, {start: 1, end: 3}>; my_arr = [1] // 校验通过 my_arr = [1,2] // 校验通过 my_arr = [1,2,3] // 校验通过 my_arr = [1,2,3,4] // 校验失败:长度超出end阈值 my_arr = [1, "string"] // 校验失败:元素类型不匹配 my_arr = [] // 校验失败:长度小于start阈值
实现逻辑说明
BuildTuple是基础计数工具:通过递归向结果元组追加元素,直到元组长度等于目标值N,用来快速生成初始长度为start的目标元素类型元组。RangeTuple负责递归生成区间内所有合法元组:从长度等于start的元组开始,每次递归向元组尾部追加一个同类型元素,同时把当前长度的元组加入结果联合集,直到元组长度等于end时终止递归,返回所有合法元组的联合类型。- 该实现天然支持元素类型校验:所有生成的元组都约束了元素类型为传入的T,类型不匹配的元素会直接触发校验失败。
注意:受TypeScript默认递归深度限制(约40~50层),如果传入的end值过大会触发类型实例化过深的报错,绝大多数日常业务场景下的长度范围都不会触发该限制,可以正常使用。
内容的提问来源于stack exchange,提问作者Baba Dan Constantin
相关产品推荐
相关产品推荐

