TypeScript中如何基于属性的枚举/类型实现另一属性的泛型关联?
TypeScript 实现属性类型关联的接口
完全可以实现这种一个属性类型由另一个属性决定的接口,下面提供两种常用方案:联合类型(直观易用)和泛型(灵活扩展)。
方法一:使用联合类型(推荐)
通过将接口拆分为多个关联的对象类型并组成联合,直接绑定fruitType和result的对应关系,TypeScript会自动做类型校验和推导。
首先定义基础类型:
// 水果类型字面量 type Apple = 'apple'; type Orange = 'orange'; type Banana = 'banana'; // 对应结果类型 interface AppleResult { appleSize: string; isCrunchy: boolean; } interface OrangeResult { orangeJuiceContent: number; hasSeeds: boolean; } interface BananaResult { bananaRipeness: 'green' | 'yellow' | 'brown'; length: number; }
然后定义联合类型的模型:
type MyFruitModel = | { id: number; fruitType: Apple; result: AppleResult } | { id: number; fruitType: Orange; result: OrangeResult } | { id: number; fruitType: Banana; result: BananaResult };
使用时的效果:
const banana: MyFruitModel = { id: 0, fruitType: 'banana', result: { bananaRipeness: 'yellow', // TypeScript会自动提示BananaResult的属性,错误属性会直接报错 length: 15 } }; // 错误示例:fruitType是apple但result用OrangeResult,会触发类型校验错误 const invalidFruit: MyFruitModel = { id: 1, fruitType: 'apple', result: { orangeJuiceContent: 50 } };
方法二:使用泛型实现
通过建立水果类型与结果类型的映射关系,用泛型约束实现属性关联,适合需要频繁扩展水果类型的场景。
先定义映射关系:
// 水果类型集合 type FruitType = 'apple' | 'orange' | 'banana'; // 水果类型到结果类型的映射 type FruitResultMap = { apple: AppleResult; orange: OrangeResult; banana: BananaResult; };
然后定义泛型接口:
interface MyFruitModel<T extends FruitType> { id: number; fruitType: T; result: FruitResultMap[T]; }
使用方式:
// 手动指定泛型参数 const orange: MyFruitModel<'orange'> = { id: 2, fruitType: 'orange', result: { orangeJuiceContent: 80, hasSeeds: false } }; // 自动推断泛型(用as const固定字面量类型,satisfies校验约束) const banana2 = { id: 3, fruitType: 'banana' as const, result: { bananaRipeness: 'brown', length: 12 } } satisfies MyFruitModel<FruitType>;
方案对比
- 联合类型:写法直观,类型校验严格,无需额外映射,适合场景简单的需求。
- 泛型:扩展性强,新增水果类型只需更新映射表,无需修改接口结构,适合需要频繁迭代的场景。
内容的提问来源于stack exchange,提问作者user3272696
相关产品推荐
相关产品推荐

