英文:
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'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.field
是Activity
的键之一(即,使用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
英文:
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<K extends keyof Activity>(
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: "id", content: 123 }); // okay
update(act, { field: "status", content: 123 }); // error! number is not string
update(act, { field: "status", content: "abc" }); // okay
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论