选择< S,K>使用动态/计算键键入 [英] Pick<S, K> type with dynamic/computed keys
问题描述
最新的 @ types / react
( v15.0.6
)利用TypeScript 2.1中为 setState
,即 Pick< S,K>
。这是一件好事,因为现在的输入是正确的,因为在更新之前不知道 setState
正在合并 this.state。
,而不是替换它。
The latest @types/react
(v15.0.6
) make use of features added in TypeScript 2.1 for setState
, namely Pick<S, K>
. Which is a good thing, because now the typings are correct, because before the update typings "didn't know" that setState
is merging this.state
, rather than replacing it.
此外,使用 Pick
可以使 setState
函数在允许输入方面非常严格。无法再将未在组件定义中定义的属性添加到状态
( React.Component $ c的第二个泛型) $ c>。
Also, using Pick
makes the setState
function very strict in terms of allowed input. It is no longer possible to add properties to the state
that aren't defined in the component definition (second generic of React.Component
.
但是定义动态更新处理程序也比较困难,例如:
But it is also harder to define a dynamic update handler. For example:
import * as React from 'react';
interface Person {
name: string;
age: number|undefined;
}
export default class PersonComponent extends React.Component<void, Person> {
constructor(props:any) {
super(props);
this.state = {
name: '',
age: undefined
};
this.handleUpdate = this.handleUpdate.bind(this);
}
handleUpdate (e:React.SyntheticEvent<HTMLInputElement>) {
const key = e.currentTarget.name as keyof Person;
const value = e.currentTarget.value;
this.setState({ [key]: value });
}
render() {
return (
<form>
<input type="text" name="name" value={this.state.name} onChange={this.handleUpdate} />
<input type="text" name="age" value={this.state.age} onChange={this.handleUpdate} />
</form>
);
}
}
setState
函数将引发以下错误
[ts] Argument of type '{ [x: string]: string; }' is not assignable
to parameter of type 'Pick<Person, "name" | "age">'.
Property 'name' is missing in type '{ [x: string]: string; }'.
即使键
的类型为名称 | 年龄
。
除了单独的 updateName $外,我找不到解决方案c $ c>和
updateAge
函数。有人知道如何将 Pick
与动态键值一起使用吗?
I can not find a solution for this, other than having a separate updateName
and updateAge
function. Does anyone know how to use Pick
with dynamic key values?
推荐答案
因此,在进行了更多研究之后,我可以提供上面代码中发生的情况的更多上下文。
So after doing more research I can provide a little more context on what is happening in the above code.
当您执行 const name = 'Bob'
变量 name
的类型为'Bob'
字符串。但是,如果将 const
替换为 let
( let name ='Bob'
)变量 name
的类型为 string
。
When you do something like const name = 'Bob'
the type of the variable name
is 'Bob'
not string. However, if you replace the const
with a let
(let name = 'Bob'
) the variable name
will be of type string
.
这个概念称为扩大。基本上,这意味着类型系统尝试尽可能明确。因为不能重新分配 const
,所以TypeScript可以推断出确切的类型。可以重新分配 let
语句。因此,TypeScript将 string
(在上面的示例中)推断为 name
的类型。
This concept is called "widening". Basically, it means that the type system tries to be as explicit as possible. Because const
can not be reassigned TypeScript can infer the exact type. let
statements can be reassigned. Thus, TypeScript will infer string
(in the above example) as the type of name
.
const key = e.currentTarget.name作为Person
的情况也是如此。 键
的类型(联盟)为 name | age
,这正是我们想要的是。 但是在表达式 this.setState({[key]:value});
变量 key
(错误地)扩展为字符串
。
The same is happening with const key = e.currentTarget.name as keyof Person
. key
will be of (union) type "name"|"age"
, which is exactly what we want it to be. But in the expression this.setState({ [key]: value });
variable key
is (incorrectly) widened to a string
.
tl; dr; 似乎TypeScript中存在错误。我将问题发布到了Github仓库,TypeScript团队正在调查问题。 :)
tl;dr; It seems like there is a bug in TypeScript. I posted the issue to the Github repo and the TypeScript team is investigating the problem. :)
作为临时解决方法,您可以执行以下操作:
As a temporary workaround you can do:
this.setState({ [key as any]: value });
这篇关于选择< S,K>使用动态/计算键键入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!