简体   繁体   中英

Infer Typescript class to return the generic type based of generic value

It is difficult to articulate exactly what I want to achieve, so I will post the code. I have a class that should fetch config that should dynamically return the correct config type based on the id specified in the contractor. Question: How should I structure my code solve my problem spesified below?

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();
  }
}

Class callee

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

The Problem:

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

在此处输入图像描述

You could use a user-defined type guard (aka type predicate) to distinguish between ConfigA and ConfigB in your get() .

Something like this one:

function isConfigA(config: ConfigA | ConfigB): config is ConfigA {
  return (config as ConfigA).propA !== undefined;
}

You could use

new ConfigService<ConfigA>("configA").get()

The issue I think is that the specific subtype cannot be enforced to be inferred from that string parameter alone because ConfigA | ConfigB ConfigA | ConfigB is already a valid generic type. And the rules for type inference are afaik that it will infer the most generic type that fits.

This way you can "help".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM