TypeScript中能否对number字面量类型应用算术映射函数?
在TypeScript中能否对数字字面量类型应用算术映射函数?
你想实现的是对数字字面量联合类型的每个成员自动执行算术运算(比如给ternary类型的每个值加1得到ternaryR),而非手动枚举结果类型。以下是可行的方案建议:
最小可复现场景
type ternary = | 0 | 1 | 2 ; /** * 期望:将数字字面量类型'ternary'的每个值偏移1 * 伪代码:type ternaryR = ternary + 1; */ // 当前只能手动编写结果类型 type ternaryR = | 1 | 2 | 3 ; const buffer: [ number, // 元数据 [number, number], [number, number], [number, number], ] = [ 10001337, [11, 12], [21, 22], [31, 32], ] function safeIncrement( i: ternaryR, ) { const iNext = i + 1; if ( Number.isInteger(iNext) && iNext > 0 && iNext < 4 ) return i + 1 as ternaryR; else throw new RangeError(""); } for ( let i: ternaryR = 1; i < 4; i = safeIncrement(i); ) buffer[i][0] = buffer[i][1] // 类型检查通过
可行方案:基于元组长度的类型算术
TypeScript本身不支持直接对数字字面量类型做算术运算,但可以利用元组长度代表数字的特性,通过元组的拼接/截取模拟加减操作,再结合分布式条件类型遍历联合类型的每个成员:
1. 通用加法类型实现
// 用元组长度模拟数字加法 type Add<T extends number, U extends number> = [...Array<T>, ...Array<U>]['length']; // 遍历联合类型的每个成员,逐个执行加法 type MapAdd<T extends number, N extends number> = T extends T ? Add<T, N> : never; // 应用到你的场景 type ternary = 0 | 1 | 2; type ternaryR = MapAdd<ternary, 1>; // 自动推导为 1 | 2 | 3
2. 递增场景的简化实现
如果只需要给每个成员加1,可以专门实现Increment类型:
// 给数字字面量类型加1 type Increment<T extends number> = [1, ...Array<T>]['length']; // 遍历联合类型执行递增 type MapIncrement<T extends number> = T extends T ? Increment<T> : never; // 应用示例 type ternaryR = MapIncrement<ternary>; // 1 | 2 | 3
3. 优化safeIncrement函数的类型推导
结合上面的类型,可以让函数返回类型自动推导,避免手动断言:
type ternary = 0 | 1 | 2; type ternaryR = MapIncrement<ternary>; function safeIncrement(i: ternaryR): Increment<typeof i> extends ternaryR ? Increment<typeof i> : never { const iNext = i + 1; if (iNext > 0 && iNext < 4) { return iNext as Increment<typeof i>; } throw new RangeError("索引超出范围"); }
方案局限性
这种基于元组的方式仅适合小范围数字(比如0~1000),如果数字过大,会导致元组类型膨胀,拖慢类型检查速度。但对于你示例中的小范围联合类型,完全够用,且比字符串转数字的方案简洁得多,无需硬编码任何数字的字符串处理逻辑。
内容的提问来源于stack exchange,提问作者Jimmy Luo
相关产品推荐
相关产品推荐

