开发者问题收集

尽管检查,对象仍可能为空

2022-05-08
898

为什么 TS 抱怨

Object possibly null

尽管我已经检查过了?

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]));
2个回答

由于这是通过键变量访问对象的属性,因此 TS 无法识别这两个语句引用的是同一个值。您可以将值存储在临时常量中以解决此问题:

const item = data[i];
if (item !== null) {
  result += item;
}

但无论如何,我不建议使用 for 循环。要么使用 for ... of ,要么使用 filterreduce 的函数式方法。

for (const item of data) {
  if (item !== null) {
    result += item;
  }
}

各种类型的访问示例,无论正确与否都可能导致错误:

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;
}

游乐场

brunnerh
2022-05-08

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

您可以使用 非空断言

result += data[i]!;

因为在这个上下文中你可以 100% 地说这不是空的。

打字稿游乐场

Lars Flieger
2022-05-08