You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 23:01:04