如何将空检查拉入打字稿中的函数

Ste*_*nTG 4 null types typescript

我有一些代码,其中有几个函数需要对对象进行空值检查,然后对其进行处理,或者如果它为空则抛出错误,如下所示:

interface SomeObject {
    doThingOne: () => string;
    doThingTwo: () => string;
}

let object: SomeObject | null; 

function doThingOne() {
  if(!object) {
    throw new Error('Object is null!');
  }
  // Typescript knows that object is not null, so it's fine with accessing its properties/methods
  return object.doThingOne();
}

function doThingTwo() {
  if(!object) {
    throw new Error('Object is null!');
  }
  return object.doThingTwo();
}
Run Code Online (Sandbox Code Playgroud)

我想将空检查提取到函数中以减少重复的代码,如下所示:

interface SomeObject {
    doThingOne: () => string;
    doThingTwo: () => string;
}

let object: SomeObject | null; 

function requireObject() {
  if(!object) {
    throw new Error('Object is null!');
  }
}

function doThingOne() {
  requireObject();
  // Typescript no longer knows that object is defined, so it gets mad at the next line
  return object.doThingOne();
}

function doThingTwo() {
  requireObject();
  return object.doThingTwo();
}
Run Code Online (Sandbox Code Playgroud)

然而,当我这样做时,打字稿在检查后不再知道它object确实存在。有没有一种干净的方法来做到这一点?

这个问题看起来很相似,但实际上不会让我节省太多代码重复,因为我仍然需要设置一个if

jca*_*alz 7

无法编写requireObject()并影响 的类型object,因为编译器不会以任何方式requireObject()将 视为相关。object(如果编译器可以管理由于函数内部封闭变量的突变而导致的所有可能的状态变化,那就太好了,但它在计算上不可行。有关一般问题,请参阅microsoft/TypeScript#9998 。)

您可以做的就是传递objectrequireObject()注释这requireObject()是一个断言函数。断言函数必须实现为void-returning (因此它们不返回任何内容),并且带注释的返回类型是以下形式的“断言谓词” asserts x is Y(其中x是函数参数之一的名称)或者只是asserts x如果您想要说的x实话

这给了我们:

function requireObject(x: any): asserts x {
  if (!x) {
    throw new Error('something is falsy here');
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以毫无错误地执行此操作:

let object: SomeObject | null;

function doThingOne() {
  requireObject(object);
  return object.doThingOne(); // okay
}

function doThingTwo() {
  requireObject(object);
  return object.doThingTwo(); // okay
}
Run Code Online (Sandbox Code Playgroud)

Playground 代码链接