You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 10:12:00