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

huangapple go评论59阅读模式
英文:

How to use a string as an object index that I know it is a key of that type

问题

```typescript
type Activity = {
  status: string,
  id: number,
  ...
  lotOfOtherProps
}
function update(activity: Activity, input: {field: string, content: string}) {
  // this got an error because field can not be used as an index
  activity[input.field] = input.content
}

但我百分之百确定这个字段是类型中可能的属性之一。

那么,如何解决这个问题?


<details>
<summary>英文:</summary>

Let&#39;s say I have a type like

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

And I have a function that update tha activity based on inputs

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
}

But I am 100% sure that this field is one of the possible props of the type.

So, how to solve this?

I have a function

答案1

得分: 0

你可以使用方括号表示法,将输入字段作为字符串来访问属性。像这样:

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

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

英文:

You can use the bracket notation to access the property using the input.field as a string. Like this:

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

The as keyof Activity syntax is called a type assertion and it tells TypeScript that input.field can be used as an index/key to access the Activity object properties.

答案2

得分: 0

为了进行类型检查,编译器需要知道不仅input.fieldActivity的键之一(即,使用keyof类型运算符keyof Activity),它还需要知道input.content是与该键对应的正确属性类型。这意味着您应该将update()input.field的类型K进行泛型化,并告诉编译器input.content将是类型Activity[K],即索引访问类型,表示“在类型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链接到代码

英文:

In order for this to type check, the compiler needs to know not only that input.field is one of the keys of Activity (i.e., keyof Activity using the keyof type operator), it also needs to know that input.content is of the correct property value type corresponding to the key. That means you should make update() generic in the type K of input.field, and tell the compiler that input.content will be of type Activity[K], the indexed access type meaning "the property type of Activity at the index of type K":

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

Now that compiles with no error, and should also provide some type safety when you call it:

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

Playground link to code

huangapple
  • 本文由 发表于 2023年2月14日 20:53:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75448131.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定