![](/img/trans.png)
[英]Why does the new `Pick<T, K extends keyof T>` type allow subsets of `K` in React's `setState()`?
[英]Pick<S, K> type with dynamic/computed keys
最新的@types/react
( v15.0.6
) 使用了 TypeScript 2.1 中为setState
添加的功能,即Pick<S, K>
。 这是一件好事,因为现在输入是正确的,因为在更新输入之前“不知道” setState
正在合并this.state
,而不是替换它。
此外,使用Pick
使setState
函数在允许的输入方面非常严格。 不再可能向组件定义中未定义的state
添加属性( React.Component
的第二个泛型。
但定义动态更新处理程序也更难。 例如:
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" | "age"
"name" | "age"
。
除了具有单独的updateName
和updateAge
函数之外,我找不到解决方案。 有谁知道如何将Pick
与动态键值一起使用?
因此,在进行更多研究之后,我可以提供更多有关上述代码中发生的情况的上下文。
当您执行类似const name = 'Bob'
的操作时,变量name
的类型是'Bob'
而不是字符串。 但是,如果您将const
替换为let
( let name = 'Bob'
),则变量name
将为string
类型。
这个概念叫做“拓宽”。 基本上,这意味着类型系统试图尽可能明确。 因为const
不能被重新赋值,TypeScript 可以推断出确切的类型。 let
语句可以重新赋值。 因此,TypeScript 会将string
(在上面的示例中)推断为name
的类型。
const key = e.currentTarget.name as keyof Person
也会发生同样的情况。 key
将是(联合)类型"name"|"age"
,这正是我们想要的。 但是在表达式中this.setState({ [key]: value });
变量key
被(错误地)扩展为string
。
TL;博士; TypeScript 中似乎存在错误。 我将问题发布到 Github 存储库,TypeScript 团队正在调查该问题。 :)
作为临时解决方法,您可以执行以下操作:
this.setState({ [key as any]: value });
塞巴斯蒂安的回答不再对我有用(尽管在某个阶段确实如此)。 我现在执行以下操作,直到它在 Typescript 核心中得到解决(根据 Sebastians 回答中列出的问题):
handleUpdate (e:React.SyntheticEvent<HTMLInputElement>) {
const newState = {};
newState[e.currentTarget.name] = e.currentTarget.value;
this.setState(newState);
}
这很蹩脚,但它有效
我认为这可能会解决您的问题。
type State = {
name: string,
age: number | undefined
};
type StateKeys = keyof State;
dynSetState(key: StateKeys, value: string) {
this.setState({
[key]: value
} as Pick<State, keyof State>)
}
如果该值不在可能的属性值类型集中,这仍然会适当地给出错误,但如果键不在可能的属性键集中,则不会给您错误。
参考:https ://github.com/DefinitelyTyped/DefinitelyTyped/issues/26635
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.