【问题标题】:Why TypeScript judge 'a' | 'b' to string?为什么 TypeScript 判断 'a' | 'b' 串起来?
【发布时间】:2019-11-22 00:08:15
【问题描述】:

我是 TypeScript、React 和英语的新手,很抱歉有歧义。我写了一个这样的函数:

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

【问题讨论】:

    标签: reactjs string typescript


    【解决方案1】:

    您可以将您的对象投射到any,就像这里建议的https://stackoverflow.com/a/46363303/9124424

    为了避免any-警告,您可以像这里建议的https://stackoverflow.com/a/49481975/9124424 那样转换为Pick&lt;State, keyof State&gt;

    【讨论】:

      【解决方案2】:

      我不知道为什么它适用于第二个。两者都不应该。真正的问题是你应该把整个对象放到setState 中,你所做的就是把新对象放在一个字段中,它与状态接口不匹配。

      为了描述更多,它只是setState(newState: ObjectAttrUniqueState ) 而不是你使用这个像setState(newState: Pick&lt;ObjectAttrUniqueState, 'name' | 'desc'&gt; )。这意味着您在参数中提供的数据不足。

      解决方案是复制之前的状态,只更改一个想要的属性:

      this.setState({
          ...this.state,
          [attr]: e.target.value,
        });
      

      【讨论】:

      • 嘿,OP 没有明确提到这一点,但我的猜测是,上面的示例中使用了类组件。所以在这里将部分对象传递给this.setState 就可以了。
      【解决方案3】:

      比如说,有一个联合字符串字面量类型的属性名:

      declare const aKey: "foo" | "bar"
      

      ,那么当通过计算属性名称表示法设置值时,您总是会返回带有索引签名的类型。编译器不知道实际访问了哪个属性。

      const o= { 
        [aKey]: true 
      }; // o: { [x: string]: boolean }
      

      显然有一个Pull Request 可以更好地缩小这些类型,但它从未被合并(这个related issue 与你的相似)。所以你可以将this.setState 的参数转换为anyPick&lt;ObjectAttrUniqueState, typeof attr&gt;

      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
        });
      }
      

      【讨论】:

        猜你喜欢
        • 2019-10-27
        • 2016-08-07
        • 2014-03-29
        • 2010-12-08
        • 2011-05-30
        • 2018-11-22
        • 2021-10-06
        • 2022-11-27
        • 2016-02-25
        相关资源
        最近更新 更多