如何在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
相关产品推荐
相关产品推荐

