首页 > 解决方案 > 为什么我不能使用索引类型推断写入对象属性

问题描述

我有这个功能

function foo<T extends { [P in K]: number }, K extends keyof T>(obj: T, key: K): void {
  const x: number = obj[key]
  obj[key] = 123 //error
}

obj[key]有类型number ,但我不能给它写数字

类型“123”不可分配给类型“T[K]”。

如何解决?

标签: typescripttypescript-genericsmapped-types

解决方案


这是按预期工作的。想象一下你这样调用foo

const obj = {a: 42} as const
foo(obj,"a") 
// foo<{readonly a: 42; }, "a">(obj: { readonly a: 42; }, key: "a"): void

Then T[K]won't be number, but (a subtype) - to42的赋值不再有效。在body 内部,我们只知道肯定是某种(的泛型约束),但不知道确切的类型是什么。123afooT[K]numberT

因此 TS 将发出错误Type '123' is not assignable to type 'T[K]'- 编译器无法确保这123是正确的类型,因为泛型类型foo. 唯一可以静态检查的类型是T[K].

要写入number某些属性K,您可以按如下方式更改签名:

function foo<K extends PropertyKey>(obj: Record<K, number>, key: K): void {
  const x: number = obj[key]
  obj[key] = 123 
}

const obj = { foo: 1, bar: true }
foo(obj, 'foo') // works

TS游乐场样本


推荐阅读