如何在TypeScript中定义4位数字的年份类型(React状态用)
如何在TypeScript中定义4位数字的年份类型
TypeScript本身无法直接在类型层面限制number的位数,但可以通过以下两种方式实现编译时或运行时的4位年份约束:
方法一:字面量联合类型(编译时严格约束)
通过递归类型生成1000到9999的数字字面量联合,让Year类型只能接受该范围内的整数:
type NumberRange< Start extends number, End extends number, Acc extends number[] = [] > = Acc['length'] extends End ? Acc[number] : Acc['length'] extends Start ? NumberRange<Start, End, [...Acc, Start]> : NumberRange<Start, End, [...Acc, Acc['length']]>; // 限定为1000-9999的4位数字类型 type Year = NumberRange<1000, 9999>; // 使用示例 const validYear: Year = 2024; // 合法 const invalidYear: Year = 999; // 编译报错
这种方式在编译阶段就能拦截不符合要求的数值,但缺点是会生成包含9000个字面量的联合类型,对类型检查性能有轻微影响。
方法二:品牌类型(编译时区分+运行时校验)
通过添加唯一品牌标记区分普通number和Year类型,配合辅助函数做运行时检查,兼顾灵活性和类型安全:
// 定义品牌类型,通过唯一标记区分类型 type Brand<T, B> = T & { __brand: B }; // 4位年份的品牌类型 type Year = Brand<number, 'Year'>; // 校验并创建合法的Year值 const createYear = (year: number): Year => { if (Number.isInteger(year) && year >= 1000 && year <= 9999) { return year as Year; } throw new Error('年份必须是4位整数'); }; // 使用示例 const myYear: Year = createYear(2024); // 合法 const badYear: Year = 123; // 编译报错(普通number无法赋值给Year类型) createYear(999); // 运行时抛出错误
这种方式不会生成庞大的字面量类型,同时通过品牌标记确保只有经过校验的值才能被当作Year类型使用,适合大多数场景。
内容的提问来源于stack exchange,提问作者Ala Eddine Menai
相关产品推荐
相关产品推荐

