Carl Rippon

Building SPAs

Carl Rippon
BlogBooks / CoursesAbout
This site uses cookies. Click here to find out more

TypeScript Assertion Signatures

April 21, 2020
typescriptreact

Typescript 3.7 introduced some cracking features such as optional chaining and nullish coalescing. There was another useful feature that TypeScript 3.7 introduced, which is called assertion signatures. In this post, we’ll find out what assertion signatures are and where we can use them.

Type guard with a type predicate

Let’s say we have the following type for various editor elements a field can have:

type Editor =
  | HTMLInputElement
  | HTMLSelectElement;

So, the editor element can be an input element or a select element.

We need to implement a function that gets the value if the editor element is a checkbox. Here’s how we could do this before TypeScript 3.7 with a type predicate:

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

The getCheckboxValue function takes in a parameter called editor of type Editor. Inside the if condition, the type of the editor parameter has been narrowed to HTMLInputElement. This means that TypeScript is happy with the checked property in editor.

Here, the isCheckbox type predicate is used to narrow the type of editor to HTMLInputElement. The return type annotation, editor is HTMLInputElement tells TypeScript that the type of editor can be narrowed to HTMLInputElement when the function returns true.

Type guard using an assertion signature

An assertion signature is an alternative approach for implementing a type guard. Let’s give this a go:

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

The assertion signature is in the assertIsCheckbox function, in the return type annotation. This is asserts editor is HTMLInputElement in our example which results in editor being narrowed to HTMLInputElement after this function has been returned.

Type guard using a general assert function

We can implement a general assert function which contains an assertion signature as follows:

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

This tells TypeScript that whatever gets passed into the condition parameter must be true if the function returns (because otherwise, it would throw an error).

We can use it in getCheckboxValue function as follows:

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

Wrap up

An assertion signature is a way of implementing a type guard to narrow the type of a variable. It is arguably closer to standard JavaScript constructs than using a type predicate.

Discuss this post on twitter

Using TypeScript with React

For React developers eager to learn TypeScript

Learn how to utilize TypeScript’s sophisticated type system to make React development faster and your code more readable
Using TypeScript with React
Find out more