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

如何在TypeScript中从泛型类型获取属性类型?

如何在TypeScript泛型类中获取属性的类型字符串用于解析逻辑

你遇到的核心问题是TypeScript的类型系统是编译时的,泛型参数T在运行时会被类型擦除,所以没办法直接从泛型T中获取属性的类型字符串——毕竟运行时根本不知道T具体是什么类型。不过我们可以通过提供运行时元数据的方式来解决这个问题,下面是具体的实现方案:

方案一:手动传入类型映射表

最直接的方式是在创建ConfigBuilder实例时,传入一个记录每个配置键对应类型名称的对象,这样运行时就能通过key拿到对应的类型字符串了。

完整修改后的代码

type Config = {
  database_host: string,
  database_pass: string | undefined,
};

const defaultConfig: Config = { database_host: 'host', database_pass: undefined };

// 定义解析器接口
interface Parser {
  parse(value: any): any;
}

class ConfigBuilder<T> {
  // 解析器字典:类型字符串对应解析逻辑
  private parserDictionary: Record<string, Parser> = {
    "string": { parse: (v) => String(v) },
    "string | undefined": { parse: (v) => v === undefined ? undefined : String(v) }
  };

  // 运行时类型映射表:key -> 类型字符串
  constructor(private typeMap: Record<keyof T, string>) {}

  public resolve(...args): T {
    // 这里补充你的resolve逻辑,比如合并默认配置、环境变量、yaml内容
    const config = { ...defaultConfig };
    // 假设foundValues是从环境变量/yaml拿到的键值对
    const foundValues = {} as Record<string, any>;

    for (const key in foundValues) {
      const configKey = key.toLowerCase() as keyof T;
      if (foundValues.hasOwnProperty(key)) {
        config[configKey] = this.parse(configKey, foundValues[key]);
      }
    }

    return config;
  }

  private parse<K extends keyof T>(key: K, value: any): T[K] {
    const type = this.getConfigKeyType(key);
    const parser = this.parserDictionary[type];
    
    if (parser) {
      // 用类型断言确保返回值符合T[K]的类型
      return parser.parse(value) as T[K];
    }
    throw new Error(`Could not find parser for type ${type}`);
  }

  private getConfigKeyType<K extends keyof T>(key: K): string {
    return this.typeMap[key];
  }
}

// 使用时传入类型映射表,TypeScript会自动校验key和类型是否匹配
const config = new ConfigBuilder<Config>({
  database_host: "string",
  database_pass: "string | undefined"
}).resolve(defaultConfig, /* 你的EnvironmentVars、YamlFiles实例 */);

方案优化:用TypeScript类型约束保证映射表正确性

为了避免手动维护类型映射表时出现错误,可以定义一个TypeMap类型,确保传入的映射表键完全匹配T的键:

type TypeMap<T> = { [K in keyof T]: string };

// 修改构造函数的参数类型
constructor(private typeMap: TypeMap<T>) {}

这样如果你的Config类型更新了,TypeScript会强制你同步更新类型映射表,避免不一致。

为什么不能直接用索引访问类型?

你尝试的type property = T[keyof T]是编译时的类型操作,但运行时没有T的类型信息——TypeScript编译成JavaScript后,泛型参数会被擦除,所以在运行时T只是一个占位符,无法用来获取具体属性的类型。必须通过运行时可访问的元数据(比如我们的typeMap)来关联key和类型字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:03:58