如何用TypeScript为枚举值属性设置唯一ID类型校验?
TypeScript 实现 EnumValue 下对象 ID 唯一性校验
需求说明
现有如下TypeScript数据结构,需添加类型校验规则:
- 每个
EnumValue枚举值对应的子对象中,所有Product类型的属性必须拥有唯一的id - 保留
as const satisfies语法,确保代码中能正确使用数据的模型类型
原始代码:
interface Product { id: number name: string; } enum EnumValue { 'VALUE1' = 'VALUE1', 'VALUE2' = 'VALUE2', 'VALUE3' = 'VALUE3', } const data = { 'VALUE1': { num1: {id: 1, name: '2'}, num2: {id: 2, name: '2'}, }, 'VALUE2': { num1: {id: 1, name: '2'}, }, 'VALUE3': { num1: {id: 1, name: '2'}, }, } as const satisfies { readonly [key in EnumValue]: { [key: string]: Product} };
已知一段针对数组对象唯一id的校验代码,但不清楚如何适配到对象结构的遍历校验。
解决方案
1. 定义辅助类型
ObjectValues<T>:提取对象的所有属性值为数组类型HasUniqueIds<T>:校验对象中所有Product的id是否唯一,重复则返回never触发类型错误
// 提取对象的所有属性值为数组 type ObjectValues<T> = T extends object ? T[keyof T][] : never; // 校验对象中所有Product的id是否唯一,重复则返回never type HasUniqueIds<T extends { [key: string]: Product }> = ObjectValues<T> extends infer Arr extends Product[] ? Arr[number]['id'] extends infer Id ? Id extends number ? // 判断当前id是否在数组中出现多次,是则返回never Extract<Arr, { id: Id }> extends [infer _, infer __, ...any[]] ? never : T : T : T : T;
2. 定义合法数据类型
基于上述辅助类型,定义ValidData类型,要求每个EnumValue对应的子对象必须通过HasUniqueIds校验:
type ValidData = { readonly [K in EnumValue]: HasUniqueIds<{ readonly [key: string]: Product }>; };
3. 应用校验到数据
将原数据的satisfies类型替换为ValidData,即可实现自动校验:
// 合法示例:无重复id,无类型错误 const validData = { VALUE1: { num1: { id: 1, name: '2' }, num2: { id: 2, name: '2' }, }, VALUE2: { num1: { id: 1, name: '2' }, }, VALUE3: { num1: { id: 1, name: '2' }, }, } as const satisfies ValidData; // 非法示例:VALUE1下存在重复id,TypeScript会抛出类型错误 const invalidData = { VALUE1: { num1: { id: 1, name: '2' }, num2: { id: 1, name: '2' }, // 此处id重复,触发错误 }, VALUE2: { num1: { id: 1, name: '2' }, }, VALUE3: { num1: { id: 1, name: '2' }, }, } as const satisfies ValidData;
原理说明
ObjectValues<T>将每个EnumValue对应的子对象转换为Product数组,方便复用数组的id唯一性校验逻辑HasUniqueIds<T>通过Extract<Arr, { id: Id }>提取所有包含当前id的元素,若提取结果长度≥2,则判定为重复id,返回never使satisfies触发类型错误ValidData通过映射类型遍历所有EnumValue,确保每个子对象都通过唯一性校验
内容的提问来源于stack exchange,提问作者mhd sah
相关产品推荐
相关产品推荐

