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

泛型与联合类型结合时Record无法索引的问题排查与解决

TypeScript泛型与联合类型索引错误问题解析

异常原因

当泛型约束为联合类型Both时,TypeScript无法追踪T['keys']和T['value']之间的关联关系:

  • T extends Both意味着T可以是A或C,TypeScript会将T['keys']解析为'a'|'b'|'c'|'d',T['value']解析为{a:string,b:string} | {c:string,d:string}。
  • 此时类型系统无法保证传入的key一定属于当前def的键集合(比如可能用'a'索引{c:string,d:string}),因此抛出索引错误。
  • 当约束改为T extends A或T extends C时,keys和value的关联是明确的,类型系统能确认key是value的有效键,所以不会报错。

正确实现方案

方案一:保留泛型关联关系

直接用Foo作为泛型约束,明确keys和value的绑定:

type Foo<K extends string, T extends Record<K, string>> = {
  keys: K
  value: T
}

type A = Foo<'a'|'b', {'a': 'A', 'b':'B'}>
type C = Foo<'c'|'d', {'c': 'C', 'd':'D'}>

function bar<K extends string, T extends Record<K, string>>(def: T, key: K) {
  return def[key];
}

// 调用示例
const aValue: A['value'] = {a: 'A', b: 'B'};
bar(aValue, 'a'); // 正常通过类型检查
bar(aValue, 'c'); // 类型报错,符合预期

方案二:基于联合类型的分布式处理

如果需要保留Both联合类型的约束,可使用分布式条件类型确保类型关联:

type Foo<K extends string, T extends Record<K, string>> = {
  keys: K
  value: T
}

type A = Foo<'a'|'b', {'a': 'A', 'b':'B'}>
type C = Foo<'c'|'d', {'c': 'C', 'd':'D'}>

type Both = A|C

function bar<T extends Both>(def: T['value'], key: T['keys']): 
  T extends {value: infer V, keys: infer K} ? K extends keyof V ? V[K] : never : never
{
  return def[key as any];
}

// 调用示例
const aValue: A['value'] = {a: 'A', b: 'B'};
const cValue: C['value'] = {c: 'C', d: 'D'};
bar(aValue, 'a'); // 返回类型为'A'
bar(cValue, 'd'); // 返回类型为'D'
bar(aValue, 'c'); // 类型报错,符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 15:37:53