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

TypeScript:如何根据字符串参数推导函数的具体返回类型?

TypeScript动态键名的类型推导方案

问题场景

现有如下TypeScript函数:

function getObjectFromString(str: string): { loading: boolean, [key: string]: any } {
    const result = {
        loading: false,
    };

    // 根据输入字符串设置键值
    result[str] = true;

    return result;
}

调用const obj = getObjectFromString('foo');时,obj的类型被推导为{ loading: boolean, [key: string]: any },但实际需求是让obj的类型为{ loading: boolean, foo: any },且对任意传入的字符串参数都能自动推导对应键名的具体类型。

可行方案:使用泛型捕获字符串字面量类型

通过泛型可以捕获传入参数的具体字符串字面量类型,进而构造出包含该键名的返回类型。以下是两种实现方式:

方式一:结合Record工具类型

function getObjectFromString<K extends string>(str: K): { loading: boolean } & Record<K, any> {
    const result = {
        loading: false,
    } as { loading: boolean } & Record<K, any>;

    result[str] = true;
    return result;
}

方式二:直接使用映射类型

function getObjectFromString<K extends string>(str: K): { loading: boolean } & { [P in K]: any } {
    const result = { loading: false } as any;
    result[str] = true;
    return result as { loading: boolean } & { [P in K]: any };
}

方案说明

  • 泛型K extends string用于捕获调用时传入的具体字符串字面量(比如传'foo'时,K就代表字面量类型'foo')
  • 返回类型通过交叉类型(&)合并loading属性和动态键名的属性,确保TS能推导出自定义的键名类型
  • 函数内部的类型断言(as)是为了让TS认可动态添加的键属于返回类型的一部分,避免类型报错

更严谨的类型限定

如果需要限定动态键对应的值的类型(比如示例中赋值的是true,属于boolean类型),可以把返回类型里的any替换为具体类型:

function getObjectFromString<K extends string>(str: K): { loading: boolean } & Record<K, boolean> {
    const result = {
        loading: false,
    } as { loading: boolean } & Record<K, boolean>;

    result[str] = true;
    return result;
}

此时调用getObjectFromString('foo')后,obj.foo的类型会被推导为boolean,比any更安全。

测试效果

const obj = getObjectFromString('foo');
// obj的类型为 { loading: boolean; foo: any }(或boolean,取决于上面的实现)
obj.loading; // 类型安全,TS能识别该属性
obj.foo; // 类型安全,TS能识别该属性
obj.bar; // TS会抛出类型错误,提示bar属性不存在

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:01:02