我试图将对象中的属性减少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]--;
}
}
}
}
答案 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)
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;
}
}
}
}