You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:12:19