TypeScript实现接口互斥属性校验:限制仅能二选一分配子接口
TypeScript联合类型互斥属性校验问题
问题场景
我定义了三个TypeScript接口x、y、z,其中z的user字段为x | y联合类型。但创建z类型对象时,同时传入name和roll属性并未触发TypeScript错误,需要实现仅允许分配name或roll其中一个属性的校验逻辑,让非法赋值触发错误。
原接口代码:
interface x{ id: number; name: string; } interface y{ id: number; roll: string; } interface z{ id: number; user: x | y; }
当前无错误但需要触发报错的对象创建代码:
let temp: z = { id: 1, user: { id: 2, name: 'User', roll: '10' } }
解决方案
TypeScript默认的联合类型允许同时包含两个类型的属性(因为联合类型是“或”的关系,但对象可以同时满足多个类型的结构),要实现互斥校验,需要让类型明确标记“对方的属性不存在”。
方法一:直接修改接口定义
给每个接口添加对方属性的never类型,明确禁止同时存在:
interface x { id: number; name: string; // 明确x类型不能有roll属性 roll?: never; } interface y { id: number; roll: string; // 明确y类型不能有name属性 name?: never; } interface z { id: number; user: x | y; }
此时如果同时传入name和roll,TypeScript会检测到属性冲突,直接触发类型错误。
方法二:用工具类型封装互斥逻辑
如果不想修改原接口,可以通过工具类型自动生成互斥类型:
interface x { id: number; name: string; } interface y { id: number; roll: string; } // 生成互斥类型的工具类型 type MutuallyExclusive<T, U> = (T & Partial<Record<keyof U, never>>) | (U & Partial<Record<keyof T, never>>); interface z { id: number; user: MutuallyExclusive<x, y>; }
这个工具类型会自动给每个类型添加对方属性的never可选类型,实现和方法一相同的互斥校验效果。
内容的提问来源于stack exchange,提问作者Arifur Rahman Arif
相关产品推荐
相关产品推荐

