如何为返回0到n数组的函数定义静态类型
实现返回静态已知类型的0到n数字数组函数
想要实现一个返回从0到n的数字数组的函数,同时希望该函数的返回值具备静态已知的数组类型。示例代码如下:
const makeFoo = (n: number) => [...Array(n).keys()]; const foo1 = [0, 1, 2] as const; // readonly [0, 1, 2] const foo2 = makeFoo(3); // number[] console.log(foo1); // [0, 1, 2] console.log(foo2); // [0, 1, 2]
尽管foo1和foo2在运行时的值相同,但它们的类型不同。请问如何定义makeFoo的返回类型,使其与foo1类似(即readonly [0, 1, ... n],其中n在静态层面也是已知的,例如通过makeFoo = <T extends number>(n: T) => ...这样的泛型方式)?
解决方案
要实现这个需求,需要结合TypeScript的字面量类型、递归条件类型和类型断言,让函数能根据输入的字面量数字n,推导出精确的只读数组类型。
1. 定义递归生成数字序列的类型
先创建一个递归类型,用来生成从0到T-1的数字元组:
type NumberSequence<T extends number, U extends number[] = []> = U['length'] extends T ? U : NumberSequence<T, [...U, U['length']]>;
这个类型的逻辑是:不断往数组U中添加当前数组的长度值,直到U的长度等于输入的T,此时U就是从0到T-1的数字元组。
2. 改造makeFoo函数
利用上面的类型,结合泛型约束和类型断言,改造函数:
const makeFoo = <T extends number>(n: T): Readonly<NumberSequence<T>> => { return [...Array(n).keys()] as Readonly<NumberSequence<T>>; };
3. 测试效果
调用时传入字面量数字,TypeScript就能推导出精确的只读数组类型:
const foo2 = makeFoo(3); // readonly [0, 1, 2] const foo3 = makeFoo(5); // readonly [0, 1, 2, 3, 4]
注意事项
- 该方案仅支持字面量数字作为输入,如果传入动态计算的
number类型变量,TypeScript无法推导出精确的元组类型,会退化为readonly number[]。 - TypeScript对递归类型有深度限制,一般支持到约1000左右的数字,超过这个范围可能会触发类型计算报错。
内容的提问来源于stack exchange,提问作者Ivan Rubinson
相关产品推荐
相关产品推荐

