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

使用联合索引类型无法正确索引对象的TypeScript问题

TypeScript联合类型Key索引对象时报错的原因及交叉类型解析

问题核心

当Key类型被收窄为具体值(如"A")时,赋值操作正常;但Key保留联合类型时,TypeScript抛出类型不兼容错误,且报错信息中出现了令人困惑的交叉类型。

1. 收窄类型正常的原因

在case "A"分支中,TypeScript通过类型收窄明确知道key的类型是"A",因此:

  • cachedData[key]的类型被推断为{A: 'A'}
  • fetchedData[key]的类型被推断为{A: 'A', otherField: string} | undefined
    此时展开cache并添加otherField后的类型,完全匹配目标属性的类型,所以赋值无报错。

2. 联合类型时报错的原因

在default分支中,key的类型仍是'A' | 'B' | 'C',TypeScript的类型检查逻辑在这里存在限制:
它无法跟踪key和cachedData[key]之间的对应关系,会错误地认为你可能给任意Key赋值任意类型的缓存数据。为了保证类型安全,它要求赋值的类型必须同时满足所有FetchedData属性类型的要求,这就导致了严格的类型校验。

3. 报错中交叉类型的来源

报错里的交叉类型{A: "A"; otherField: string;} & {B: "B"; otherField: string;} & {C: "C"; otherField: string;},来自TypeScript对fetchedData[key]的类型推断:
当索引是联合类型时,TS会将FetchedData[Key]的所有可能类型进行合并约束,错误地生成了所有属性类型的交叉类型——它认为赋值必须对所有Key都有效,而不仅仅是当前的key对应的类型。但实际上我们的赋值是和当前key严格对应的,这个推断不符合实际场景。

解决方案

方案1:类型断言

直接告诉TypeScript当前赋值的类型是匹配的:

default : {
    const cache = cachedData[key]
    fetchedData[key] = {...cache, otherField: 'otherField'} as FetchedData[Key];
}

方案2:泛型函数封装

通过泛型让TypeScript跟踪Key和对应值的类型关系:

type Key = keyof FetchedData;

function updateData<K extends Key>(key: K, fetched: FetchedData, cached: CachedData) {
    fetched[key] = {...cached[key], otherField: 'otherField'};
}

// 在default分支中调用
default : {
    updateData(key, fetchedData, cachedData);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 19:32:16