TypeScript泛型集合Getter函数类型推断异常问题求助
解决方案:利用泛型索引类型实现类型安全的Getter
要让Getter函数根据传入的键返回对应具体类型,核心是通过泛型约束和索引类型查询,让TypeScript关联键与对应值的类型映射关系。
示例代码实现
先定义基础的Entry类、结构枚举和接口,再改造Collection类:
class Entry<T> { constructor(public value: T) {} } enum Keys { Name = 'name', Age = 'age' } interface CollectionStructure { [Keys.Name]: Entry<string>; [Keys.Age]: Entry<number>; } // 给Collection添加泛型参数S,约束为包含Entry类型的对象 class Collection<S extends Record<string, Entry<any>>> { constructor(public state: S) {} // 泛型K限定为S的键,返回值类型为S[K],精准匹配键对应的类型 getEntry<K extends keyof S>(key: K): S[K] { return this.state[key]; } } // 实例化时传入符合结构的state,TypeScript会自动推断泛型类型 const col = new Collection({ [Keys.Name]: new Entry('Alice'), [Keys.Age]: new Entry(30) }); // 现在getEntry能正确推断类型 const nameEntry = col.getEntry(Keys.Name); // Entry<string> const ageEntry = col.getEntry(Keys.Age); // Entry<number>
为什么原来的实现不行?
你之前的getEntry方法仅把参数类型设为Keys枚举,但TypeScript无法将这个枚举与state的具体键值类型做关联,只能返回所有可能值的联合类型Entry<string>|Entry<number>。
而通过给Collection添加泛型参数S,并让getEntry的泛型K继承keyof S,TypeScript就能明确知道:传入的键K对应的返回值就是S中该键的具体类型,从而实现精准的类型推断。
变体:固定默认结构
如果你的Collection始终基于CollectionStructure,可以给泛型设置默认值,简化实例化:
class Collection<S extends Record<string, Entry<any>> = CollectionStructure> { public state: S = {} as S; constructor(initialState?: Partial<S>) { if (initialState) Object.assign(this.state, initialState); } getEntry<K extends keyof S>(key: K): S[K] { return this.state[key]; } } // 无需手动指定泛型,直接实例化 const col = new Collection({ [Keys.Name]: new Entry('Bob'), [Keys.Age]: new Entry(28) });
内容的提问来源于stack exchange,提问作者Joshua Dannemann
相关产品推荐
相关产品推荐

