为什么TypeScript判断为“ a”? 'b'字符串?

时间:2019-11-21 07:31:31

标签: reactjs string typescript

我是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'判断为字符串类型,这会导致这种类型的错误信息。 那我该如何解决这个问题呢?

3 个答案:

答案 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的参数转换为anyPick<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
  });
}