我是TypeScript,React和English的新手,很抱歉。我写这样的函数:
interface ObjectAttrUniqueState {
editVisible: boolean;
currentId: number;
selectedUnique: number[];
name: string;
desc: string;
}
// some other code.....
handleChangeForm(e: React.ChangeEvent<HTMLInputElement>, attr: 'desc' | 'name') {
this.setState({
[attr]: e.target.value,
});
}
TypeScript输出如下:
Type '{ [x: string]: string; }' is missing the following properties from type 'Pick<ObjectAttrUniqueState, "editVisible" | "currentId" | "selectedUnique" | "name" | "desc">': editVisible, currentId, selectedUnique, name, desc
我尝试了这项工作
handleChangeForm(e: React.ChangeEvent<HTMLInputElement>, attr: 'name') {
this.setState({
[attr]: e.target.value,
});
}
我认为TypeScript将'name'判断为简单的字符串标识符,将'name'|'desc'判断为字符串类型,这会导致这种类型的错误信息。 那我该如何解决这个问题呢?
答案 0 :(得分:0)
您可以按照此处https://stackoverflow.com/a/46363303/9124424的建议将对象投射到any
为避免any
警告,您可以像此处https://stackoverflow.com/a/49481975/9124424所示那样强制转换为Pick<State, keyof State>
答案 1 :(得分:0)
我不知道为什么它可以继续工作。两者都不应该。问题实际上是您应该将整个对象放入setState
中,而您要做的是将新对象放入一个字段,而该字段与状态接口不匹配。
要描述更多,它只是setState(newState: ObjectAttrUniqueState )
,而不是像setState(newState: Pick<ObjectAttrUniqueState, 'name' | 'desc'> )
这样使用。这意味着您无法在参数中提供足够的数据。
解决方案是复制以前的状态,并仅更改一个所需的属性:
this.setState({
...this.state,
[attr]: e.target.value,
});
答案 2 :(得分:0)
说,有一个带有联合字符串文字类型的属性名称:
declare const aKey: "foo" | "bar"
,那么当通过计算的属性名称表示法设置值时,总是返回带有索引签名的类型。编译器不知道实际访问了哪个属性。
const o= {
[aKey]: true
}; // o: { [x: string]: boolean }
显然,有一个Pull Request可以将这些类型的范围缩小一些,但从未合并过(此related issue与您的相似)。因此,您可以将this.setState
的参数转换为any
或Pick<ObjectAttrUniqueState, typeof attr>
。
handleChangeForm(
e: React.ChangeEvent<HTMLInputElement>,
attr: "desc" | "name"
) {
this.setState({
[attr]: e.target.value
} as Pick<ObjectAttrUniqueState, typeof attr>);
}
如果需要,可以缩小关键字范围以区分大小写:
if (attr === "desc") {
this.setState({
desc: e.target.value
});
}