如何让TypeScript函数根据输入ID返回对应类型的对象?
用泛型实现可扩展的水果类型查询函数
要解决这个扩展性问题,核心是通过映射类型+泛型约束把水果ID和对应类型绑定起来,新增类型时只需要扩展映射关系,无需修改查询函数的核心逻辑。以下是具体实现步骤:
1. 定义水果类型与ID映射
先明确每种水果的结构,再建立ID到类型的映射关系,让TypeScript能通过ID自动关联到对应类型:
// 具体水果类型定义 type Apple = { id: 'apple'; properties: { color: 'red' | 'green'; sweetness: number; }; }; type Orange = { id: 'orange'; properties: { diameter: number; hasSegments: boolean; }; }; // 建立ID到对应水果类型的映射表 type FruitMap = { apple: Apple; orange: Orange; }; // 提取所有合法的水果ID类型(自动推导为 'apple' | 'orange') type FruitId = keyof FruitMap;
2. 改造查询函数为泛型函数
让fetchFruitById接收一个泛型参数,约束为合法的FruitId,返回值直接对应FruitMap中该ID关联的类型。模拟数据库调用的someMethodThatReturnsFruit也同步适配泛型:
// 模拟数据库查询,根据ID返回对应结构的数据 function someMethodThatReturnsFruit<T extends FruitId>(id: T): FruitMap[T] { // 实际场景替换为真实数据库查询逻辑 if (id === 'apple') { return { id: 'apple', properties: { color: 'red', sweetness: 8 } } as FruitMap[T]; } else { return { id: 'orange', properties: { diameter: 10, hasSegments: true } } as FruitMap[T]; } } // 泛型版本的查询函数 function fetchFruitById<T extends FruitId>(id: T): FruitMap[T] { return someMethodThatReturnsFruit(id); }
3. 使用与扩展性验证
调用时TypeScript会自动根据传入的ID推导返回类型,无需手动断言:
const apple = fetchFruitById('apple'); // apple 类型为 Apple,可直接访问 apple.properties.color、apple.properties.sweetness const orange = fetchFruitById('orange'); // orange 类型为 Orange,可直接访问 orange.properties.diameter、orange.properties.hasSegments
如果新增水果类型(比如Banana),只需要做两步:
- 定义
Banana类型 - 在
FruitMap中添加banana: Banana的映射 - (可选)更新
someMethodThatReturnsFruit的查询逻辑
完全不需要修改fetchFruitById的代码,扩展性拉满。
异步场景适配
如果数据库调用是异步的,只需把返回类型改为Promise即可:
async function someMethodThatReturnsFruit<T extends FruitId>(id: T): Promise<FruitMap[T]> { return new Promise(resolve => { setTimeout(() => { if (id === 'apple') { resolve({ id: 'apple', properties: { color: 'green', sweetness: 7 } } as FruitMap[T]); } else if (id === 'orange') { resolve({ id: 'orange', properties: { diameter: 9, hasSegments: true } } as FruitMap[T]); } }, 100); }); } async function fetchFruitById<T extends FruitId>(id: T): Promise<FruitMap[T]> { return someMethodThatReturnsFruit(id); }
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

