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

如何让Typescript ConfigService类根据配置ID动态返回对应泛型类型?

解决TypeScript中ConfigService动态返回配置的类型识别问题

问题背景

需要实现一个ConfigService类,根据构造函数传入的配置ID动态返回对应类型的配置,但调用get()方法后,TypeScript无法正确识别具体配置类型,报错“Property 'propA' does not exist on type 'Configs'”。

原代码

export type ConfigA = {
  id: "configA";
  name: string;
  propA: string;
};

export type ConfigB = {
  id: "configB";
  name: string;
  propB: string;
};

export type Configs = ConfigA | ConfigB;

export class ConfigService<C extends Configs> {
  private readonly configCollection: CollectionReference<C>;

  constructor(private configName: C["id"]) {
    this.configCollection = db.collection("config") as CollectionReference<C>;
  }

  public async get() {
    const configSnap = await this.configCollection.doc(this.configName).get();
    return configSnap.data();
  }
}

调用代码

const configA = await new ConfigService("configA").get();
const propA = configA.propA;

报错信息

Property 'propA' does not exist on type 'Configs'.
Property 'propA' does not exist on type 'ConfigB'

解决方案

核心问题是原泛型约束未建立配置ID与具体配置类型的精准关联,TypeScript无法从传入的ID推导出对应的具体类型。通过以下调整解决:

调整后的代码

export type ConfigA = {
  id: "configA";
  name: string;
  propA: string;
};

export type ConfigB = {
  id: "configB";
  name: string;
  propB: string;
};

// 建立配置ID到具体类型的映射
export type ConfigMap = {
  configA: ConfigA;
  configB: ConfigB;
};

// 保留原Configs类型(可选,用于需要泛指所有配置的场景)
export type Configs = ConfigMap[keyof ConfigMap];

export class ConfigService<K extends keyof ConfigMap> {
  private readonly configCollection: CollectionReference<ConfigMap[K]>;

  constructor(private configName: K) {
    this.configCollection = db.collection("config") as CollectionReference<ConfigMap[K]>;
  }

  public async get(): Promise<ConfigMap[K] | undefined> {
    const configSnap = await this.configCollection.doc(this.configName).get();
    return configSnap.data();
  }
}

调用示例

const configA = await new ConfigService("configA").get();
if (configA) {
  const propA = configA.propA; // TypeScript可正确识别类型,无报错
}

const configB = await new ConfigService("configB").get();
if (configB) {
  const propB = configB.propB; // 同样支持ConfigB的类型识别
}

调整说明

  1. 新增ConfigMap映射:将每个配置ID与对应的具体类型绑定,让TypeScript能通过ID精准定位到目标类型,避免联合类型的模糊性。
  2. 泛型参数调整:将ConfigService的泛型改为K extends keyof ConfigMap,构造函数传入的configName会被约束为映射的键,TypeScript据此自动推导返回的具体配置类型。
  3. 明确返回类型:get()方法返回ConfigMap[K] | undefined(适配Firestore的data()可能返回undefined的情况),确保调用后类型清晰。

内容的提问来源于stack exchange,提问作者Jeremy Walters

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 01:50:36