I'm trying to decrease a property in an object by 1 if it exists and is greater than 0 but TypeScript won't compile this code whatever I try.
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]--;
}
}
}
}
In Typescript all properties of a type with an index signature have to adhere to that signature, which is why it requires you to include undefined as part of the index value. This is a mechanism to make sure that the type of a property is consistent regardless of if you access it using bracket notation (status["burning"]) or with dot notation (status.burning).
But you can get around this by using an intersection type to combine the index signature and your other properties:
type IStatus = {
[key: string]: number; // <= No undefined here anymore
} & {
burning?: number;
firing?: number;
}
Using that, this.status[key] is inferred to have type number, but this.status.burning is inferred to have type number | undefined.
As noted earlier, you'll want to be careful since now you can change the inferred type of the burning property by how you access it. If you use this.status["burning"], the type is inferred as just number.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With