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

TypeScript如何将联合类型的键用作索引?

解决TypeScript联合类型索引匹配报错

问题场景

需要根据输入更新对应对象的属性,输入可能对应两种不同结构的对象(Foo/Bar),尝试用联合类型的键作为索引时触发类型错误。

代码示例

interface Foo{
  featureFOO1: boolean
  featureFOO2: boolean
}
interface Bar{
  featureBAR1: boolean
  featureBAR2: boolean
}

interface T {
  foo: Foo;
  bar: Bar
}

const input = {
  type: 'foo', // 也可能是'bar'
  featureName: 'featureFOO1', // 也可能是'featureBAR1'
  value: false
}

const list = {
  foo: {
    featureFOO1: true,
    featureFOO2: false
  },
  bar: {
    featureBAR1: true,
    featureBAR2: false
  }
}
type Union = Foo | Bar
type KeysOfUnion<T> = T extends T ? keyof T: never
type AvailableKeys = KeysOfUnion<Union>

list[input.type as keyof T][input.featureName as AvailableKeys] = input.value

报错信息(翻译后)

错误:元素隐式拥有'any'类型,因为类型为'AvailableKeys'的表达式无法用于索引类型'{ featureFOO1: boolean; featureFOO2: boolean; } | { featureBAR1: boolean; featureBAR2: boolean; }'。属性'featureFOO1'不存在于类型'{ featureFOO1: boolean; featureFOO2: boolean; } | { featureBAR1: boolean; featureBAR2: boolean; }'上。(7053)

解决方案

问题根源是TypeScript无法确认input.type和input.featureName是一一对应的——比如当type为foo时,featureName可能被传入属于bar的键,所以类型检查不通过。

方案1:封装泛型函数(推荐)

通过泛型绑定type和featureName的关联关系,让TypeScript能验证两者的匹配性:

function updateFeature<K extends keyof T>(
  list: T,
  input: { type: K; featureName: keyof T[K]; value: boolean }
) {
  list[input.type][input.featureName] = input.value;
}

// 调用函数更新属性
updateFeature(list, input);

方案2:直接用类型断言(适合不封装函数的场景)

如果不想封装函数,可以通过泛型类型断言明确键的归属:

type Input<K extends keyof T> = { type: K; featureName: keyof T[K]; value: boolean };
(list[input.type as keyof T] as T[keyof T])[input.featureName as keyof T[(typeof input)['type']]] = input.value;

第一种方案不仅解决了类型错误,还让代码结构更清晰,同时保证了类型安全,避免传入不匹配的type和featureName。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 14:24:52