了解什么是断言签名以及我们可以在哪里使用它们

320 阅读2分钟

Typescript 3.7引入了一些破解功能,如可选链nullish凝聚。TypeScript 3.7还引入了另一个有用的功能,这就是断言签名。在这篇文章中,我们将了解什么是断言签名以及我们可以在哪里使用它们。

带有类型谓词的类型保护

假设我们对一个字段可以拥有的各种编辑元素有以下类型:

type Editor =
  | HTMLInputElement
  | HTMLSelectElement;

所以,编辑元素可以是一个input 元素或select 元素。

我们需要实现一个函数,如果编辑元素是一个复选框,就可以得到这个值。在TypeScript 3.7之前,我们可以用一个类型谓词来完成这个任务:

function getCheckboxValue(editor: Editor) {
  if (isCheckbox(editor)) {
    // type of editor narrowed to HTMLInputElement
    return editor.checked;
  }
  throw new Error("editor is not a checkbox");
}

function isCheckbox(
  editor: Editor
): editor is HTMLInputElement {
  return "checked" in editor;
}

getCheckboxValue 函数接收了一个名为editor 的参数,类型为Editor 。在if 条件里面,editor 参数的类型已经被缩小到HTMLInputElement 。这意味着TypeScript对editor 中的checked 属性感到满意。

在这里,isCheckbox 类型谓词被用来将editor 的类型缩小到HTMLInputElement 。返回类型注释,editor is HTMLInputElement 告诉 TypeScript,当函数返回true 时,editor 的类型可以被缩小到HTMLInputElement

使用断言签名的类型保护

断言签名是实现类型保护的另一种方法。让我们试一试吧:

function getCheckboxValue(editor: Editor) {
  assertIsCheckbox(editor);  // type of editor narrowed to HTMLInputElement
  return editor.checked;
}

function assertIsCheckbox(
  editor: Editor
): asserts editor is HTMLInputElement {  if (!("checked" in editor)) {
    throw new Error("Not a checkbox");
  }
}

断言签名在assertIsCheckbox 函数中,在返回类型注释中。在我们的例子中,这是asserts editor is HTMLInputElement ,其结果是在这个函数被返回后,editor 被缩小为HTMLInputElement

使用一般断言函数的类型保护

我们可以实现一个包含断言签名的一般assert 函数,如下所示:

function assert(
  condition: any,
  msg?: string
): asserts condition {  if (!condition) {
    throw new Error(msg);
  }
}

这告诉TypeScript,如果函数返回,无论传入condition 参数的是什么,都必须是true (因为否则,它将抛出一个错误)。

我们可以在getCheckboxValue 函数中使用它,如下所示:

function getCheckboxValue(editor: Editor) {
  assert(
    "checked" in editor,
    "editor is not a checkbox"
  );
  // type of editor narrowed to HTMLInputElement
  return editor.checked;
}

包裹起来

断言签名是实现类型保护的一种方式,用于缩小变量的类型。可以说,它比使用类型谓词更接近于标准的JavaScript结构。