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

TypeScript中含keyof的泛型不被接受,报错TS2322的原因?

TypeScript泛型函数类型错误解析

原问题代码

interface Iface {
  add?: string;
  create?: string;
}

// TS2322: Type 'string' is not assignable to type 'T[keyof T]'.
function f<T extends Iface|Record<string, string>>(key:keyof T, obj:T){
  obj[key] = 'something';
}

function fi(key: keyof Iface, obj: Iface) {
  obj[key] = 'something';
}

function fr(key: string, obj: Record<string, string>) {
  obj[key] = 'something';
}

函数f的报错原因

泛型约束T extends Iface | Record<string, string>允许T是Iface的任意子类型,或是Record<string, string>的任意子类型。报错的核心原因是TypeScript对泛型的严格类型检查逻辑:

  • 当T是Iface的子类型时,T的属性可以是string的字面量类型或更窄的子类型(比如type StrictSub = { add: 'init' },该类型完全符合extends Iface的约束)。此时T[keyof T]的类型是该字面量类型(如'init'),而赋值的'something'是宽泛的string类型,无法兼容更窄的字面量类型。
  • TypeScript在处理泛型时会覆盖所有可能的合法子类型,因此它无法确定'something'能适配所有T[keyof T]的可能类型,最终抛出类型不兼容错误。

对比非泛型的fi和fr:

  • fi直接使用Iface类型,obj[key]的类型为string | undefined,string类型的'something'可安全赋值。
  • fr直接使用Record<string, string>,obj[key]的类型就是string,赋值逻辑完全合法。

补充问题:函数f3的问题

代码如下:

function f3<T extends Record<string, string>>(key:string, obj:T){
  obj[key] = 'something'; 
}

这里的问题是key的类型范围超出了T的合法键集:

  • 泛型T是Record<string, string>的子类型,意味着T的键只是string类型的一个子集(比如type User = { name: string }就符合约束)。
  • 参数key的类型是string,允许传入任何字符串,包括不属于T键集的值(比如给User类型的obj传入key='age')。此时obj[key]并非T的合法属性,TypeScript会阻止这种潜在的非法赋值,因此会触发类型错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 12:35:27