TypeScript枚举扩展时接口属性依赖判断的简洁实现方案咨询
TypeScript接口属性依赖优化方案
背景
实现TypeScript接口中属性依赖另一个属性的场景有多种思路。
现有实现方案
经过尝试,目前采用的方案如下:
enum MyEnum { One = 'One', Two = 'Two', Three = 'Three', // 后续可能新增更多枚举成员 } interface MyInterface<T extends MyEnum> { prop1: string, prop2: boolean, prop3: T, prop4: T extends MyEnum.One ? OneSpecificInterface : T extends MyEnum.Two ? TwoSpecificInterface : T extends MyEnum.Three ? ThreeSpecificInterface : never // 后续新增枚举成员需继续扩展此处逻辑 }
这里prop3是MyEnum的枚举值,prop4的类型完全由prop3决定:比如prop3为MyEnum.One时,prop4必须符合OneSpecificInterface类型(包含该枚举对应的专属字段)。由于不同枚举对应的prop4结构差异大,无法用单一接口统一,但又需要一个包含这四个属性的统一接口,所以用了上述方案。
问题
当前方案能正常运行,但随着MyEnum枚举成员增加,prop4处的三元类型判断链会越来越长,有没有更简洁优雅的实现方式?如果现有方案确实没有优化空间也可以接受,但希望能确认;同时也欢迎其他能实现相同类型检查效果、且可读性好的方案。
优化方案
可以用类型映射表来替代冗长的三元判断链,不仅更简洁,后续新增枚举成员时只需更新映射表即可,维护性更强:
步骤1:定义枚举与对应类型的映射
// 先定义各个专属接口 interface OneSpecificInterface { oneField: string; } interface TwoSpecificInterface { twoField: number; } interface ThreeSpecificInterface { threeField: boolean; } // 建立枚举到对应类型的映射表 type EnumToTypeMap = { [MyEnum.One]: OneSpecificInterface; [MyEnum.Two]: TwoSpecificInterface; [MyEnum.Three]: ThreeSpecificInterface; // 新增枚举成员时,直接在这里添加对应的类型映射即可 };
步骤2:重构统一接口
enum MyEnum { One = 'One', Two = 'Two', Three = 'Three', // 后续新增枚举成员 } interface MyInterface<T extends MyEnum> { prop1: string; prop2: boolean; prop3: T; prop4: EnumToTypeMap[T]; // 直接通过映射表获取对应类型,无需三元链 }
验证效果
使用时TypeScript会自动根据prop3的枚举值推断prop4的类型:
// 正确示例:prop3为One时,prop4必须符合OneSpecificInterface const validOne: MyInterface<MyEnum.One> = { prop1: "test", prop2: true, prop3: MyEnum.One, prop4: { oneField: "hello" } }; // 错误示例:prop3为Two时,prop4不符合TwoSpecificInterface会报错 const invalidTwo: MyInterface<MyEnum.Two> = { prop1: "test", prop2: false, prop3: MyEnum.Two, prop4: { oneField: "wrong" } // 类型错误,此处需要twoField: number };
额外优化:自动约束枚举范围
如果希望确保EnumToTypeMap覆盖所有MyEnum成员,可以添加一个类型检查:
// 强制要求EnumToTypeMap包含MyEnum的所有成员,遗漏时会报错 type EnsureEnumCoverage = keyof EnumToTypeMap extends MyEnum ? MyEnum extends keyof EnumToTypeMap ? true : never : never; // 触发检查:如果EnumToTypeMap有遗漏,下面的类型会报错 type CheckCoverage = EnsureEnumCoverage;
这样后续新增枚举成员时,若忘记更新EnumToTypeMap,TypeScript会直接提示错误,避免遗漏。
内容的提问来源于stack exchange,提问作者pez
相关产品推荐
相关产品推荐

