Reputation:
Why is TS complaining
Object possibly null
despite my check?
let sum = (data: [...(number | null)[]]): number => {
let result: number = 0;
for (let i = 0; i < data.length; i++)
if(data[i]!==null){
result += data[i]; // here is complain Object possibly null
}
return result;
};
console.log(sum([1, 2, null, 4]));
Upvotes: 1
Views: 1243
Reputation: 2562
WARNING: If the iterable object has a similar getter, then the first check in the if condition will call it once and then the assignment will call it a second time. The value can change between the if and the assignment. e.g.:
Math.random() > 0.5 ? null : 42
You could use a Non-null assertion:
result += data[i]!;
Since you can 100% say in this context this is not null.
Upvotes: 0
Reputation: 185445
Since this is accessing a property of an object via key variable, TS does not recognize that both statements refer to the same value. You can store the value in a temporary constant to fix this:
const item = data[i];
if (item !== null) {
result += item;
}
But I would not recommend using for
loops anyway. Either use for ... of
or a functional approach using filter
and reduce
.
for (const item of data) {
if (item !== null) {
result += item;
}
}
Examples of various types of access that rightly or wrongly may cause errors:
const o = {
x: 12 as number | null,
}
let key = 'x' as keyof typeof o;
if (o.x != null) {
console.log(o.x + 1); // OK
}
if (o.x != null) {
doSomething();
console.log(o.x + 1); // Wrong but allowed
}
if (o[key] != null) {
console.log(o[key] + 1); // Error
}
function doSomething() {
o.x = null;
}
const arr: (number | null)[] = [12];
if (arr[0] != null) {
console.log(arr[0] + 1); // OK
}
if (arr[0] != null) {
doSomething2();
console.log(arr[0] + 1); // Wrong but allowed
}
let i = 0;
if (arr[i] != null) {
console.log(arr[i] + 1); // Error
}
function doSomething2() {
arr[0] = null;
}
Upvotes: 5