TypeScript泛型类读取泛型键映射类型时报错求助
解决泛型联合类型映射的索引类型不匹配问题
问题核心在于TypeScript无法在泛型上下文中将value.type的类型收窄为T['type']的具体成员,而是将其推断为宽泛的string类型,导致与myMap的键类型不匹配。以下是三种可行的解决方案:
方案1:将getValue改为泛型方法,直接接收type参数
跳过整个实例,直接传入类型标识,让TypeScript明确索引的键类型:
type A = { type: 'a'; }; type B = { type: 'b'; }; type C = A | B; type UnionType = { type: string; }; class MyClass<T extends UnionType> { private myMap: { [type in T['type']]?: Extract<T, { type: type }> } = {}; setValue(type: T['type'], value: Extract<T, { type: typeof type }>) { this.myMap[type] = value; } getValue<K extends T['type']>(type: K): Extract<T, { type: K }> | undefined { return this.myMap[type]; } } // 使用示例 const cls = new MyClass<C>(); cls.setValue('a', { type: 'a' }); const aVal = cls.getValue('a'); // 类型自动推断为A | undefined
方案2:保留接收实例的方式,添加泛型约束与类型断言
如果必须接收整个T类型的实例作为参数,通过泛型约束绑定实例的type属性,再用断言帮助TypeScript完成类型推断:
type A = { type: 'a'; }; type B = { type: 'b'; }; type C = A | B; type UnionType = { type: string; }; class MyClass<T extends UnionType> { private myMap: { [type in T['type']]?: Extract<T, { type: type }> } = {}; setValue(type: T['type'], value: Extract<T, { type: typeof type }>) { this.myMap[type] = value; } getValue<V extends T>(value: V): Extract<T, { type: V['type'] }> | undefined { return this.myMap[value.type as V['type']]; } } // 使用示例 const cls = new MyClass<C>(); const aInstance = { type: 'a' } as A; cls.setValue('a', aInstance); const fetchedVal = cls.getValue(aInstance); // 类型自动推断为A | undefined
方案3:优化UnionType定义,从根源强制类型收窄
修改UnionType的type属性定义,让TypeScript将其识别为字符串字面量类型而非宽泛的string,避免类型推断偏差:
type A = { type: 'a'; }; type B = { type: 'b'; }; type C = A | B; // 用string & {}让TypeScript将type识别为字面量类型 type UnionType = { type: string & {}; }; class MyClass<T extends UnionType> { private myMap: { [type in T['type']]?: Extract<T, { type: type }> } = {}; setValue(type: T['type'], value: Extract<T, { type: typeof type }>) { this.myMap[type] = value; } getValue(value: T): Extract<T, { type: typeof value.type }> | undefined { // 此时value.type会被正确推断为T['type']的成员,无需额外断言 return this.myMap[value.type]; } }
你可以根据实际业务场景选择最合适的方案。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

