TypeScript如何实现仅接受数字const assertion作为参数的函数?
实现方案
这个需求可以实现,核心思路是通过类型约束过滤掉宽泛的number类型,仅允许数字字面量类型传入。
核心原理
数字字面量类型(比如1、5)和宽泛的number类型的区别是:number extends 数字字面量的结果为false,number extends number的结果为true,我们可以基于这个特性写过滤逻辑。
完整实现代码
你原有的元组生成泛型不需要修改,仅需要调整函数的类型定义即可:
方案1:兼容TS 4.x版本
type TupleFromCount< T, N extends number, S extends T[] = [], > = S['length'] extends N ? S : TupleFromCount<T, N, [T, ...S]>; // 过滤宽泛number类型的工具类型 type OnlyLiteral<N extends number> = number extends N ? never : N; // 调整后的函数定义,保留你需要的默认值配置 function getRecords<T extends number = 10, K>( page: number, itemsPerPage: OnlyLiteral<T>, ): TupleFromCount<K, T> { // 运行时创建数组,用类型断言告知TS类型符合要求 return new Array(itemsPerPage).fill(null) as TupleFromCount<K, T>; }
调用测试
// ✅ 合法,返回类型为 [string, string, string, string, string] const res1 = getRecords<string>(1, 5 as const); // ❌ 类型报错:参数类型number不能赋值给never const count = 5; const res2 = getRecords<string>(1, count); // ❌ 类型报错:参数类型number不能赋值给never const res3 = getRecords<string>(1, 5);
方案2:TS 5.0+ 更简洁的const泛型方案
TS 5.0新增了const类型参数修饰符,可以自动将入参推断为字面量类型,不需要用户手动写as const:
type TupleFromCount< T, N extends number, S extends T[] = [], > = S['length'] extends N ? S : TupleFromCount<T, N, [T, ...S]>; // 用const修饰泛型T,自动推断数字字面量 function getRecords<const T extends number = 10, K>( page: number, itemsPerPage: T, ): TupleFromCount<K, T> { return new Array(itemsPerPage).fill(null) as TupleFromCount<K, T>; }
调用测试
// ✅ 合法,不需要手动写as const,自动推断T为5,返回长度为5的元组 const res1 = getRecords<string>(1, 5); // ❌ 类型报错:传入宽泛number类型时TupleFromCount会触发递归超限错误,等同于禁止传入 const count = 5; const res2 = getRecords<string>(1, count);
内容的提问来源于stack exchange,提问作者Sri
相关产品推荐
相关产品推荐

