首页 > 解决方案 > 如何将空检查提取到方法中并获得有效的空类型检查?

问题描述

这假设 strictNullChecks 为真。

如果多个方法依赖于一个不为 null 的值,则每个方法都应检查该值并在它为 null 时抛出异常。最好将该空检查提取到辅助方法中,而不是在任何地方复制它。但是,如果这样做,我们将无法对每个方法中的值进行类型检查。

例如,不提取空检查:

class FooClass {
  public foo: number | null = null;

  public thisNeedsFooToNotBeNull(): void {
    if (this.foo === null) {
      throw new Error('foo should not be null');
    }
    doStuff(this.foo);
  }
}

function doStuff(foo: number) {
  console.log(`foo is ${foo}`);
}

随着提取:

class FooClass {
  public foo: number | null = null;

  private validateFoo(): void {
    if (this.foo === null) {
      throw new Error('foo should not be null');
    }
  }


  public thisNeedsFooToNotBeNull(): void {
    this.validateFoo();
    doStuff(this.foo);
  }
}

function doStuff(foo: number) {
  console.log(`foo is ${foo}`);
}

在第二个版本中,我们得到了 TypeScript 错误doStuff(this.foo);,说:

Argument of type 'number | null' is not assignable to parameter of type 'number'.
  Type 'null' is not assignable to type 'number' ts(2345)

有没有办法让 TypeScript 处理这种类型检查提取?

标签: typescript

解决方案


当 TypeScript 3.7 发布时,它将具有允许您将 -returning 函数标记为类型断言asserts修饰符void,类似于用户定义的类型保护允许您将boolean-returning 函数标记为类型检查。

所以很快(或者现在如果你安装typescript@next)你应该能够validateFoo()像这样注释:

private validateFoo(): asserts this is { foo: number } {
  if (this.foo === null) {
    throw new Error('foo should not be null')
  }
}

这里我们说的是对validateFoo()返回的调用asserts this is { foo: number },这意味着如果validateFoo()返回,它将thisFooClass(其foo属性是number | null)缩小到this & { foo: number },这意味着foo属性不会是null

其余代码应按预期编译:

public thisNeedsFooToNotBeNull(): void {
  this.validateFoo();
  doStuff(this.foo); // no error now
}

希望有帮助;祝你好运!

链接到代码


推荐阅读