typescript 如何使用字符串作为对象索引,我知道它是该类型的键

sq1bmfud  于 2023-02-17  发布在  TypeScript
关注(0)|答案(2)|浏览(209)

假设我有一种类型

type Activity = {
  status: string,
  id: number,
  ...
  lotOfOhterProps
}

我有一个函数可以根据输入更新活动

function update(actitvity: Activity, input: {field: string, content:string}){
  // this got an error because field can not be used as index
  activity[input.field]=input.content
}

但我百分之百肯定这个字段是类型的可能 prop 之一。
那么,如何解决这个问题呢?
我有一个功能

vs3odd8k

vs3odd8k1#

您可以使用括号表示法来访问属性,并将input.field作为字符串使用,如下所示:

function update(activity: Activity, input: {field: string, content: string}) {
  activity[input.field as keyof Activity] = input.content;
}

as keyof Activity语法称为类型Assert,它告诉TypeScript input.field可以用作索引/键来访问Activity对象属性。

dbf7pr2w

dbf7pr2w2#

为了进行类型检查,编译器不仅需要知道input.fieldActivity的键之一(即,使用keyof类型运算符的keyof Activity),它还需要知道input.content是对应于该键的正确的属性 * 值 * 类型。这意味着您应该使update()generic成为input.fieldK类型,并告诉编译器input.content将成为Activity[K]类型,indexed access type表示"在类型K的索引处的Activity的属性类型":

function update<K extends keyof Activity>(
  activity: Activity,
  input: { field: K, content: Activity[K] }
) {
  activity[input.field] = input.content;
}

既然编译时没有错误,并且在调用时还应该提供一些类型安全:

declare const act: Activity;
update(act, { field: "id", content: 123 }); // okay
update(act, { field: "status", content: 123 }); // error! number is not string
update(act, { field: "status", content: "abc" }); // okay

Playground代码链接

相关问题