Reputation: 5760
I have the following code:
isEmpty(vehicle: VehicleTitle) {
return this.options && this.options[vehicle.type] && this.options[vehicle.type].length === 0;
}
The IDE (VSCode) points to this.options[vehicle.type].length
and says
Object is possibly 'null'
Don't you think this is a false alarm? What is wrong here?
EDIT
Minimal reproducible example here.
Upvotes: 1
Views: 216
Reputation: 29087
Here is a previous bug along these lines That bug was fixed in July 2019 but the behaviour that was affected was:
const obj: { [key: string]: any[] | null } = { prop: [] };
obj["prop"] && obj["prop"].length; //error
obj.prop && obj.prop.length; //OK
Since version 3.6.0 that's no longer the case and both lines are accepted. It seems that now there is a ever so slightly different issue but the outline is the same:
const obj: { [key: string]: any[] | null } = { prop: [] };
const key = "prop" as const;
obj[key] && obj[key].length; //error
obj.prop && obj.prop.length; //OK
When using any variable, even a constant, to do the property access then TypeScript reports the same error as before.
There is a similar older bug that is to do with bracket notation in general not being treated the same as dot notation. That one had been closed in August 2018 but has been reopened 12 days ago (Match 2020). It appears like this the team is aware of this problem and are revisiting the latter issue for a fix.
In the meantime, here are few ways to avoid the compilation error:
You can simply do a non-null assertion using the postfix !
operator and you will correct the problem:
isEmpty(vehicle: VehicleTitle) {
return this.options && this.options[vehicle.type] && this.options[vehicle.type]!.length === 0;
// ^
}
If you want to avoid the assertion, you can just fetch the value and then use it. That will assure the compiler that you aren't actually fetching two different values:
isEmpty(vehicle: VehicleTitle) {
const value = this.options && this.options[vehicle.type];
return value && value.length === 0;
}
Typescript also has a feature that will do the same check for you, called optional chaining. It's a postfix ?
after each property that might not exist:
isEmpty(vehicle: VehicleTitle) {
return this.options?.[vehicle.type]?.length === 0;
// ^ ^
}
Upvotes: 3