TypeScript中如何让函数返回对应索引子类型而非联合子类型?
问题描述
我有一个包含不同类型子元素的复杂对象:
const stores = { A: { dataA: 'something A', getDataA(){ return this.dataA; } }, B: { dataB: 'something B', getDataB(){ return this.dataB; } } }
我用下面的方式获取子元素A:
type TStore = typeof stores; function getStore(key: keyof TStore){ return stores[key] } const child = getStore('A');
但问题是无法访问child的属性,因为它的类型是联合类型:
const child: { dataA: string; getDataA(): string; } | { dataB: string; getDataB(): string; }
而我期望child的类型是对应键的具体子类型:
const child: { dataA: string; getDataA(): string; }
我知道有个能正常工作的函数,但它需要传入对象参数,在我的场景里多余:
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; }
请问怎么让getStore函数的表现和getProperty一致?
更新
实际上我是想给MobX实现一个从组合stores中获取属性的辅助函数,现有函数如下:
const useStores = <T extends object = any, K extends keyof T = keyof T>(key: K) => { const stores = useContext<T>(StoreContext); return stores[key]; }; const child = useStores<TStore>('B');
但它还是返回子类型的联合类型。StoreContext是React.Context,创建时无法确定类型,所以初始类型为any,后续会做类型转换。
解决方案
针对基础的getStore函数
给getStore添加泛型约束,让TypeScript根据传入的键推断对应的具体子类型:
type TStore = typeof stores; function getStore<K extends keyof TStore>(key: K): TStore[K] { return stores[key]; } const child = getStore('A'); // 现在类型为{ dataA: string; getDataA(): string; }
通过泛型K绑定键与返回值的类型关联,TypeScript会自动根据传入的键返回精确的子类型,而非联合类型。
针对MobX的useStores函数
调整泛型参数的关联逻辑,同时确保StoreContext的类型转换准确:
// 方式1:明确泛型关联,让TypeScript自动推断 const useStores = <T extends object, K extends keyof T>(key: K) => { const stores = useContext<T>(StoreContext); return stores[key]; }; // 调用时显式指定T为TStore,TypeScript会自动匹配K对应的子类型 const child = useStores<TStore>('B');
如果StoreContext初始类型为any,可以在useContext时强制转换为目标类型,进一步简化函数:
const useStores = <K extends keyof TStore>(key: K): TStore[K] => { const stores = useContext(StoreContext) as TStore; return stores[key]; }; const child = useStores('B'); // 直接返回B对应的子类型
内容的提问来源于stack exchange,提问作者Nolesh
相关产品推荐
相关产品推荐

