问题描述
最新的 @types/react
(v15.0.6
) 利用 TypeScript 2.1 中为 setState
添加的功能,即 选择<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
函数在允许输入方面非常严格.不再可能向 state
添加未在组件定义中定义的属性(React.Component
的第二个泛型.
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; }'.
即使 key
的类型是 "name" |年龄"
.
除了拥有单独的 updateName
和 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'
not 字符串.但是,如果您将 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 as keyof Person
也是如此.key
将是(联合)类型 "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>使用动态/计算键键入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!