TypeScript泛型类约束适配问题:实现类实例类型、构造函数与字符串键的兼容匹配
TypeScript泛型类约束适配问题:实现类实例类型、构造函数与字符串键的兼容匹配
看起来你需要让Container的get方法实现一套「双向约束」:既允许泛型T指定类的实例类型(比如A),又能兼容字符串等原始键,同时还要严格过滤掉构造函数类型作为T的情况。我们可以通过建立键类型与目标值类型的双向映射来解决这个问题,具体方案如下:
1. 定义核心辅助类型
首先我们需要几个辅助类型来处理「构造函数→实例类型」的转换,以及键与值的双向映射:
// 标记构造函数类型:匹配任何可以new出实例的类型 type Constructor<T = any> = new (...args: any[]) => T; // 辅助类型:从键类型推导目标返回值类型 // - 如果键是构造函数,返回实例类型;否则返回键本身 type KeyToValue<K> = K extends Constructor<infer Instance> ? Instance : K; // 辅助类型:从目标值类型推导对应的键类型 // - 如果目标值是实例类型,返回对应的构造函数类型;如果是原始类型,返回其本身 type ValueToKey<T, KeysRaw> = T extends InstanceType<Extract<KeysRaw, Constructor>> ? Extract<KeysRaw, Constructor<T>> : Extract<KeysRaw, T>;
2. 自动推导Records的键与值类型
基于你的records数组,我们可以自动生成原始键类型和允许的返回值类型,无需手动维护:
class A { a = 1 } class B { b = 2 } const records = [ { key: A, }, { key: B, }, { key: "stringKey1", } ] as const; // 原始键的联合类型:typeof A | typeof B | "stringKey1" type RecordsKeysRaw = (typeof records)[number]['key']; // 允许的返回值联合类型:A | B | "stringKey1" type RecordsValues = KeyToValue<RecordsKeysRaw>;
3. 修改Container类实现约束
调整Container的泛型参数,让它同时接收原始键类型和允许的返回值类型,然后在get方法中通过ValueToKey关联泛型T(返回值类型)与传入的key参数:
class Container<KeysRaw, Values> { // 泛型T默认设为any,满足你value1返回any的需求;同时约束T只能是Values或any get<T extends Values | any = any>(key: T extends Values ? ValueToKey<T, KeysRaw> : never): T { return 'value' as T; } } // 初始化Container,传入我们自动推导的类型 const container = new Container<RecordsKeysRaw, RecordsValues>();
4. 验证预期效果
现在测试你要求的所有场景,完全符合你的预期:
// 场景1:不指定泛型,默认返回any,类型检查通过 const value1 = container.get(A); // ✅ 无错误,value1: any // 场景2:指定T为构造函数类型(typeof A),不在允许的返回值联合中,报错 const value2 = container.get<typeof A>(A); // ❌ 错误:Type 'typeof A' does not satisfy the constraint 'A | B | "stringKey1"' // 场景3:指定T为实例类型A,传入对应的构造函数key,通过检查 const value3 = container.get<A>(A); // ✅ 无错误,value3: A // 场景4:字符串键测试,指定T为"stringKey1",传入对应字符串,通过检查 const value4 = container.get<"stringKey1">("stringKey1"); // ✅ 无错误,value4: "stringKey1" // 场景5:错误的键与泛型组合,触发类型错误 const value5 = container.get<A>("stringKey1"); // ❌ 错误:Type '"stringKey1"' is not assignable to type 'typeof A'
关键逻辑说明
KeyToValue负责把原始键(构造函数/字符串)转换成你期望的返回值类型(实例/字符串本身)ValueToKey负责反向校验:当你指定返回值类型T时,传入的key必须是能对应到T的合法键(比如T=A时,key必须是typeof A)Container的get方法通过泛型约束,确保T只能是你允许的返回值类型,同时关联key的合法性,完全满足你对类型检查和推断的需求
内容来源于stack exchange
相关产品推荐
相关产品推荐

