HomepageExploring TypeScript (TS 5.8 Edition)
You can support this book: buy it or donate
(Ad, please don’t block.)

5 Notation used in this book

This chapter explains functionality that is used in the code examples to explain results and errors. We have to consider two levels:

The functions and generic types that help us, have to be imported: The import statements to do so are shown in this chapter, but omitted elsewhere in this book.

5.1 JavaScript level: assert.*

Expected results are checked via the following assertion functions from the Node.js module node:assert:

This is an example of using these assertions:

import assert from 'node:assert/strict';

assert.equal(
  3 + ' apples',
  '3 apples'
);

assert.deepEqual(
  [...['a', 'b'], ...['c', 'd']],
  ['a', 'b', 'c', 'd']
);

assert.throws(
  () => Object.freeze({}).prop = true,
  /^TypeError: Cannot add property prop, object is not extensible/
);

In the first line, the specifier of the imported module has the suffix /strict. That enables strict assertion mode, which uses === and not == for comparisons.

5.2 Type level: assertType<T>(v)

Function assertType() is provided by the TypeScript library asserttt.

The function call assertType<T>(v) asserts that the (dynamic) value v has the (static) type T:

import { assertType } from 'asserttt';

let value = 123;
assertType<number>(value);

5.3 Type level: Assert<B>

asserttt also provides the utility type Assert<B>, which asserts that the type B (usually an instantiated generic type) is true:

import { type Assert, type Equal, type Not } from 'asserttt';

type Pair<X> = [X, X];
type _ = [
  Assert<Equal<
    Pair<'a'>, ['a', 'a']
  >>,
  Assert<Not<Equal<
    Pair<'a'>, ['x', 'x']
  >>>,
];

asserttt has several predicates (generic types that construct booleans) that we can use with Assert<>. In the previous example, we have used:

5.4 Type level: @ts-expect-error

In this book, @ts-expect-error is used to show TypeScript compiler errors:

// @ts-expect-error: The value 'null' cannot be used here.
const value = null.myProp;

How does TypeScript handle such a directive?

In other words: TypeScript checks that there is an error but not what error it is. All text after @ts-expect-error is ignored (including the colon).

To get more thorough checks, I use the tool ts-expect-error which checks if the suppressed error messages match the texts after @ts-expect-error:.

5.5 Isn’t this book’s notation kind of ugly?

When it comes to displaying type information for TypeScript code, there are some very pretty approaches out there – e.g. Shiki Twoslash which uses the twoslash syntax.

This book uses in-code checks (as described above) even though that doesn’t look as nice. Why?