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

为何T继承Record<number,X>与Record<string,X>时T[keyof T]表现不同?

该类型行为差异的根本原因

核心是TypeScript对string/number两类索引签名的约束范围规则不同,再叠加泛型约束的最小满足特性,最终导致了校验结果的差异:

  • 泛型约束的基础逻辑是T extends XXX只要求T至少匹配XXX的结构,允许T额外挂载XXX未定义的任意属性。
  • 当约束写为Record<string, {b: boolean}>时,TS对齐了JavaScript运行时“数字索引会隐式转为字符串存储”的行为,强制要求:类型中所有字符串、数字键对应的属性,都必须符合string索引签名的返回类型。此时TS为了类型检查的实用性做了简化:计算T[keyof T]时直接取索引签名对应的{b: boolean}类型,忽略使用场景极少的symbol类型额外属性,因此访问['b']字段可以正常通过校验。
  • 当约束换成Record<number, {b: boolean}>时,number索引签名只会限制T里所有数字键的属性必须是{b: boolean},对T里可能存在的字符串、symbol键的属性类型完全没有约束力。举个最简单的例子:T = {1: {b: true}, username: 'foo'}这个类型完全满足Record<number, {b: boolean}>的约束,但此时T[keyof T]的类型是{b: boolean} | string,联合类型里的string根本不存在b属性,TS自然会抛出ts(2536)错误,提示Type 'b' cannot be used to index type 'T[keyof T]'。

如果要让number约束的版本也通过校验,只需要限定只取数字键对应的属性即可:

interface I<T extends Record<number, {b: boolean}>> {
  x: T[number & keyof T]['b'];
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:06:20