如何在TypeScript中声明适配数组索引的自然数类型?
TypeScript中声明自然数类型的几种方案
自然数(非负整数)正好匹配数组索引的合法范围,以下是几种在TypeScript中实现该类型的实用方案:
方案一:品牌类型(Branded Type)结合运行时校验
通过品牌类型标记合法的自然数,同时在运行时确保输入符合要求,兼顾编译时约束和运行时安全:
// 定义品牌类型,用唯一的私有属性标记自然数 type NaturalNumber = number & { __naturalNumberBrand: never }; // 转换函数:将普通number转为NaturalNumber,不符合条件则抛出错误 function toNaturalNumber(n: number): NaturalNumber { if (n >= 0 && Number.isInteger(n)) { return n as NaturalNumber; } throw new Error('输入必须是非负整数'); } // 使用示例 const validIndex = toNaturalNumber(3); const arr = ['a', 'b', 'c', 'd']; console.log(arr[validIndex]); // 合法 // 以下代码会报错:编译时类型不匹配,运行时也会抛出错误 // arr[toNaturalNumber(-1)]; // arr[toNaturalNumber(2.5)];
这种方案的优势是严格区分自然数和普通number,只要类型是NaturalNumber,就能确保它是合法的数组索引。
方案二:编译时有限范围自然数类型
如果你的数组索引有明确的上限(比如0到99),可以用递归类型生成固定范围的自然数,纯编译时约束:
// 递归生成自然数类型的辅助类型 type _NaturalRange<Max extends number, Acc extends number[] = []> = Acc['length'] extends Max ? Acc[number] : _NaturalRange<Max, [...Acc, Acc['length']]>; // 生成0到99的自然数类型 type NaturalNumber0To99 = _NaturalRange<100>; // 使用示例:限制数组索引必须在0-99之间 function getArrayItem<T>(arr: T[], index: NaturalNumber0To99): T { return arr[index]; } getArrayItem([1, 2, 3], 2); // 合法 // 以下代码编译时报错 // getArrayItem([1,2,3], -1); // getArrayItem([1,2,3], 100);
注意:这种方法受限于TypeScript的递归深度限制,不适合生成过大范围的类型。
方案三:类型守卫(Type Guard)
通过类型守卫在运行时校验输入,编译时自动缩小类型范围,适合动态场景:
// 类型守卫函数:判断输入是否为自然数 function isNaturalNumber(n: unknown): n is number { return typeof n === 'number' && n >= 0 && Number.isInteger(n); } // 使用示例 const arr = [10, 20, 30]; const maybeIndex: unknown = 1; if (isNaturalNumber(maybeIndex)) { console.log(arr[maybeIndex]); // 合法,编译时自动识别maybeIndex为自然数类型 } else { console.error('索引必须是非负整数'); }
这种方案灵活度高,无需提前转换类型,适合处理动态传入的索引值。
内容的提问来源于stack exchange,提问作者XCSenior
相关产品推荐
相关产品推荐

