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

TypeScript泛型函数如何正确返回对象键的对应类型?

TypeScript配置管理的类型收窄问题解决办法

你当前的代码中,SettingsProvider的get方法泛型设计导致类型推导失效——调用get<ServerSettings>('port')时,返回值类型是ServerSettings所有属性类型的联合string | number | boolean,而非预期的number。核心原因是get方法的泛型S与类内部存储的settings类型没有强关联,TypeScript无法确认传入的S就是当前实例的配置类型。

最优解决:将泛型绑定到类级别

把泛型从get方法移到SettingsProvider类上,让类的实例与具体配置类型绑定,这样get方法可以直接基于实例的配置类型推导属性类型,无需手动传入泛型:

interface Settings {}

interface ServerSettings extends Settings {
    host: string;
    port: number;
    valid: boolean;
}

interface SomeOtherSettings extends Settings {
    enabled: boolean;
}

// 类级别泛型绑定具体配置类型
class SettingsProvider<S extends Settings> {
    constructor(private settings: S) {}

    // 基于类的泛型S推导key对应的类型
    public get<K extends keyof S>(key: K): S[K] {
        return this.settings[key];
    }
}

const settings: ServerSettings & SomeOtherSettings = {
    host: 'localhost',
    port: 8080,
    valid: true,
    enabled: false,
};
const provider = new SettingsProvider(settings);
const port = provider.get('port'); // 类型自动推导为number
const host = provider.get('host'); // 类型自动推导为string
const enabled = provider.get('enabled'); // 类型自动推导为boolean

为什么这个方案可行?

类初始化时就通过泛型S锁定了配置的具体类型,get方法的K约束为keyof S,TypeScript可以精准关联每个key对应的属性类型,完全避免了冗余的泛型参数传递。

若需保留原类结构的替代方案

如果必须让SettingsProvider类保持无泛型的设计,可以通过在get方法中添加泛型约束,让S与实例的settings类型关联,但这种写法仍需手动传入泛型,仅比双泛型略简洁:

class SettingsProvider {
    constructor(private settings: Settings) {}

    public get<S extends typeof this.settings, K extends keyof S>(key: K): S[K] {
        return (this.settings as S)[key];
    }
}

// 使用时仍需传入泛型,但无需额外指定Key
const port = provider.get<typeof settings>('port'); // 类型为number

不过这种写法不如类级别泛型简洁,优先推荐第一种方案。

内容的提问来源于stack exchange,提问作者c4k

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:02:08