TypeScript中能否实现指定一个属性时必须同时指定另一个属性?
如何在TypeScript中实现“要么全有要么全无”的属性约束?
当然可以实现!你想要的是一种**“要么全有要么全无”**的属性约束——也就是要么完全不设置canJump和howHigh,要么两个属性一起设置。咱们先拆解下你原来的写法为什么达不到预期:
你提到的Thing | (Thing & Jump)确实会让canJump和howHigh变成可选属性,因为联合类型的规则是:只要满足其中一个分支的要求就行。所以只设置canJump: true却不设howHigh时,编译器会认为这个值匹配Thing分支(毕竟Thing里没有这两个属性),自然不会报错。
可行的解决方案
咱们可以通过两个辅助类型组合,完美实现这个约束,就是你提到的Artem的方案,我给你详细解释下:
// 基础类型定义 type Thing = { name: string } type Jump = { canJump: true; howHigh: number } // 辅助类型1:将传入类型的所有属性转为可选的never类型 // 意思是:这些属性要么不存在,要么只能赋值为never(而never没有合法值,相当于禁止单独设置) type OptNever<T> = { [K in keyof T]?: never } // 辅助类型2:二选一约束——要么完整包含T的所有属性,要么完全不设置 type AllOrNone<T> = T | OptNever<T> // 最终目标类型:必须有name属性,同时canJump和howHigh要么全有要么全无 type MightJump = Thing & AllOrNone<Jump>
测试验证
咱们来验证下这个类型的效果:
// ✅ 合法:仅包含必填的name属性 const validThing1: MightJump = { name: 'hi' } // ✅ 合法:同时包含name、canJump和howHigh const validThing2: MightJump = { name: 'hi', canJump: true, howHigh: 5 } // ❌ 报错:只设置了canJump,缺少howHigh const invalidThing1: MightJump = { name: 'hi', canJump: true } // ❌ 报错:只设置了howHigh,缺少canJump const invalidThing2: MightJump = { name: 'hi', howHigh: 5 }
关于编译器修改的思考
其实TypeScript目前的类型系统(映射类型、交叉类型、联合类型的组合)已经能很好地实现这类需求,不需要专门修改编译器。如果非要原生支持的话,可能需要引入**“依赖属性约束”**的语法——比如允许直接在类型定义里声明“如果属性A存在,则属性B必须存在”,不用借助辅助类型。不过现有方案已经足够简洁灵活,完全能满足需求。
内容的提问来源于stack exchange,提问作者fcrick
相关产品推荐
相关产品推荐

