如何在TypeScript中强制对象拥有联合类型指定的属性?
问题描述
我定义了以下类型:
type MyUnionType = "propA" | "propB" type MyType = { myProp: MyUnionType } type SomeOtherType = MyType & { /* 其他属性 */ }
现在我想扩展MyType,实现类似下面伪代码的效果:
type MyType = { myProp: MyUnionType, [key in MyUnionType]: any // 伪代码 }
使得我可以这样使用:
const obj: SomeOtherType = { myProp: "propA", propA: "some value" // 如果缺失,编译器会报错 // 其他属性... }
我试过一些方法也搜过资料,但没找到解决方案。
编辑:我已经按照要求从MyUnionType中移除了string类型。
解决方案
你需要通过泛型结合索引类型来实现这种依赖约束,具体写法如下:
type MyUnionType = "propA" | "propB"; // 泛型类型,捕获 myProp 的具体值 type MyType<T extends MyUnionType> = { myProp: T; } & Record<T, any>; // 扩展其他属性的类型 type SomeOtherType<T extends MyUnionType> = MyType<T> & { // 这里添加你的其他自定义属性,示例: extraProp?: number; };
使用示例
直接指定泛型参数时,TypeScript会强制校验对应属性是否存在:
// 合法:指定 myProp 为 "propA",同时提供了 propA 属性 const validObj: SomeOtherType<"propA"> = { myProp: "propA", propA: "hello", extraProp: 123 }; // 报错:缺失 propB 属性 const invalidObj: SomeOtherType<"propB"> = { myProp: "propB", extraProp: 456 };
如果不想手动指定泛型参数,可以用工具函数自动推导:
function createTargetObj<T extends MyUnionType>(obj: SomeOtherType<T>) { return obj; } // 自动推导类型,无需手动声明 const autoObj = createTargetObj({ myProp: "propB", propB: "world", extraProp: 789 }); // 同样报错:未提供 propA 属性 const autoInvalidObj = createTargetObj({ myProp: "propA", extraProp: 0 });
这种实现的核心是用泛型捕获myProp的具体值,再通过Record<T, any>强制要求该值对应的属性必须存在,联合类型中的其他属性则不会被强制校验。
内容的提问来源于stack exchange,提问作者Gabriele Buffolino
相关产品推荐
相关产品推荐

