如何定义包含联合类型所有成员的TypeScript对象数组类型?
实现包含联合类型/枚举所有成员的对象数组类型检查
要实现「数组必须包含联合类型/枚举的所有成员作为value字段值,否则类型检查报错」的需求,不能直接用SelectValue<Union>[](这种写法只要求数组元素是联合类型的一员,不强制全覆盖),需要自定义工具类型来做强制检查。
完整实现代码
// 基础选项对象类型:修正原代码中label的字面量类型错误,改为通用string类型 export type SelectValue<T = any> = { value: T; label: string; }; // 定义联合类型选项 type Options = "email" | "sms"; // 核心工具类型:强制数组必须包含联合类型的所有成员 type AllUnionMembersArray<T, U extends T = T> = [U] extends [never] ? [] : ( { [K in U]: SelectValue<K> }[U][] & (T extends U ? never : [SelectValue<Exclude<T, U>>, ...AllUnionMembersArray<Exclude<T, U>>]) ); // ✅ 正确示例:包含所有联合成员,类型检查通过 const validValues: AllUnionMembersArray<Options> = [ { value: "email", label: "Email" }, { value: "sms", label: "短信" }, ]; // ❌ 错误示例:缺少"sms"成员,类型检查报错 const invalidValues: AllUnionMembersArray<Options> = [ { value: "email", label: "Email" }, ];
适配枚举类型的写法
如果用枚举替代联合类型,同样可以复用这个工具类型:
// 定义枚举 enum NotificationType { Email = "email", Sms = "sms", } // ✅ 正确示例:包含所有枚举成员 const enumValidValues: AllUnionMembersArray<NotificationType> = [ { value: NotificationType.Email, label: "Email" }, { value: NotificationType.Sms, label: "短信" }, ]; // ❌ 错误示例:缺少枚举成员,类型检查报错 const enumInvalidValues: AllUnionMembersArray<NotificationType> = [ { value: NotificationType.Email, label: "Email" }, ];
原理说明
工具类型AllUnionMembersArray通过递归拆解联合类型,强制数组必须包含每个成员对应的SelectValue实例:
- 利用
Exclude<T, U>逐步剔除已包含的成员,递归检查剩余成员是否都被覆盖 - 通过交叉类型
&同时约束数组元素的类型范围和必须包含的成员数量
内容的提问来源于stack exchange,提问作者Carl Wirkus
相关产品推荐
相关产品推荐

