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

为何TypeScript会为计算属性的值推断出异常类型?

TypeScript计算属性的类型推断异常排查与解决

我第一次编写以下函数时遇到了意外行为:

function splatIfDefinedBad<K extends string, V>(
    key: K,
    value: V
): Partial<Record<K, V>> {
    if (value === undefined) {
        return {}
    }
    return { [key] : value }
}

TypeScript编译器抛出错误:

Type '{ [x: string]: V & ({} | null); }' is not assignable to type 'Partial<Record<K, V>>.'

我无法理解value的推断类型中& ({} | null)部分的来源。

换一种对象构建方式后,问题得以解决:

function splatIfDefinedGood<K extends string, V>(
    key: K,
    value: V
): Partial<Record<K, V>> {
    if (value === undefined) {
        return {}
    }
    const output: Partial<Record<K, V>> = {};
    output[key] = value;
    return output;
}

一开始我以为是计算属性的特性导致{ [key]: value }可能生成{ [key]: null },即便类型V不包含null。

后来我注意到{} | null表示“除undefined外的任意值”(因为{}类型本身代表“除null或undefined外的任意值”),因此推测这和TypeScript的类型推断机制有关?它尝试将V收窄为排除undefined的类型,但在处理类似V & Not<undefined>(假设存在该映射类型)时无法正确统一类型?而splatIfDefinedGood的写法是反向操作——在已知类型的对象上添加K对应的V类型属性,而非从“任意值”收窄到“非undefined值”?

编辑补充:
正如@ruakh指出,问题根源只是K被拓宽成了string!以下写法同样可以正常运行:

function splatIfDefined2<K extends string, V>(
    key: K,
    value: V
): Partial<Record<K, V>> {
    if (value === undefined) {
        return {}
    }
    return { [key as K] : value } as { [k in K]: V & ({} | null) }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:12:24