如何让TypeScript的IntRange类型支持负数范围?
解决TypeScript IntRange支持负数范围的问题
原有的IntRange类型依赖Enumerate通过数组长度递归生成整数,但数组长度只能是非负数,遇到起始值为负数的情况时,递归永远无法触发终止条件,直接导致TS2589: Type instantiation is excessively deep and possibly infinite错误。
下面是修改后的实现,能支持包含负数的整数范围:
修改后的类型代码
// 生成从0到绝对值N-1的整数枚举 type EnumerateAbs<N extends number, Acc extends number[] = []> = Acc['length'] extends N ? Acc[number] : EnumerateAbs<N, [...Acc, Acc['length']]>; // 计算两个数的绝对值差 type AbsDiff<A extends number, B extends number> = `${A}` extends `-${infer NumA extends number}` ? `${B}` extends `-${infer NumB extends number}` ? NumA extends NumB ? 0 : NumA > NumB ? NumA - NumB : NumB - NumA : NumA + B : `${B}` extends `-${infer NumB extends number}` ? A + NumB : A > B ? A - B : B - A; // 支持正负范围的IntRange type IntRange<F extends number, T extends number> = F extends T ? F : F extends infer FNum extends number ? T extends infer TNum extends number ? FNum < TNum ? EnumerateAbs<AbsDiff<FNum, TNum>> extends infer R extends number ? R + FNum : never : EnumerateAbs<AbsDiff<FNum, TNum>> extends infer R extends number ? TNum + R : never : never : never;
关键逻辑说明
EnumerateAbs:只负责生成非负的整数枚举,避开负数导致的递归死循环;AbsDiff:通过模板字符串解析数字符号,计算两个数之间的绝对值差,确定需要生成的整数数量;IntRange核心:- 如果起始值小于结束值,就从起始值开始,累加
EnumerateAbs生成的非负数,得到正向范围; - 如果起始值大于结束值,就从结束值开始累加,得到反向范围;
- 处理起始值等于结束值的边界情况,直接返回该数值。
- 如果起始值小于结束值,就从起始值开始,累加
测试用例
// 正整数范围:25 | 26 | 27 | 28 | 29 type PositiveRange = IntRange<25, 30>; // 包含负数的范围:-25 | -24 | ... | 3 | 4 type NegativeIncludedRange = IntRange<-25, 5>; // 反向范围:-5 | -4 | ... | 8 | 9 type ReverseRange = IntRange<10, -5>;
内容的提问来源于stack exchange,提问作者Tyler V.
相关产品推荐
相关产品推荐

