TypeScript抱怨任何'隐含任何'或者'可能未定义'即使不可能

时间:2018-04-11 23:05:37

标签: typescript

我试图将对象中的属性减少1,如果它存在且大于0但是TypeScript不会在我尝试的情况下编译此代码。

interface IStatus {
  [key: string]: number | undefined; // <= I don't want undefined here but it complains since the params are optional
  burning?: number;
  firing?: number;
}

class Thing {
  public status: IStatus = {};
  private processStatus() {
    for (const key in this.status) {
      if (
        this.status.hasOwnProperty(key) &&
        this !== undefined &&
        this.status !== undefined &&
        this.status[key] !== undefined && // <= Complains about implicit any without the index signature
        this.status[key] > 0 // <= Complains about possibly undefined with the index signature
      ) {
        this.status[key]--;
      }
    }
  }
}

3 个答案:

答案 0 :(得分:4)

在Typescript中,具有索引签名的类型的所有属性都必须遵循该签名,这就是为什么它要求您将undefined作为索引值的一部分。这是一种确保属性类型一致的机制,无论您是使用括号表示法(status["burning"])还是使用点表示法(status.burning)访问它。

但是你可以通过使用交集类型来组合索引签名和其他属性来解决这个问题:

type IStatus = {
  [key: string]: number; // <= No undefined here anymore
} & {
  burning?: number;
  firing?: number;
}

使用它,推断this.status[key]的类型为number,但推断this.status.burning的类型为number | undefined

如前所述,您需要小心,因为现在您可以根据访问方式更改burning属性的推断类型。如果您使用this.status["burning"],则类型推断为number

答案 1 :(得分:2)

使用type assertion(感叹号)可以消除

Object is possibly 'undefined'错误:

  if (
    ...
    this.status[key]! > 0
  ) {
    this.status[key]!--;
  }

如果可以通过正确的打字来解决问题(如另一个答案所示),那就更好了。

答案 2 :(得分:2)

编译器不会“记住”this.status[key] !== undefined检查的结果,它是已知的issue / limitation。解决方法是使用中间变量:

interface IStatus {
  [key: string]: number | undefined; // <= I don't want undefined here but it complains since the params are optional
  burning?: number;
  firing?: number;
}

class Thing {
  public status: IStatus = {};
  private processStatus() {
      for (const key in this.status) {
          const value = this.status[key];  
          if (value !== undefined && value > 0) {
              this.status[key] = value - 1;
          }
      }
  }
}