typestar

Type predicates in TypeScript

A function returning x is T teaches the compiler what you checked.

type Run = { lang: string; tpm: number };

function isRun(value: unknown): value is Run {
  return (
    typeof value === "object" &&
    value !== null &&
    "lang" in value &&
    typeof (value as Run).lang === "string" &&
    typeof (value as Run).tpm === "number"
  );
}

function assertRun(value: unknown): asserts value is Run {
  if (!isRun(value)) throw new TypeError("not a run");
}

function isDefined<T>(value: T | null | undefined): value is T {
  return value !== null && value !== undefined;
}

const raw: unknown = { lang: "ts", tpm: 98 };
if (isRun(raw)) console.log(raw.lang.toUpperCase());

assertRun(raw);
console.log(raw.tpm + 1);
console.log([1, null, 2, undefined].filter(isDefined));

How it works

  1. The predicate narrows at every call site.
  2. It is the honest way to validate data from outside.
  3. An assertion signature narrows without returning a value.

Keywords and builtins used here

The run, in numbers

Lines
26
Characters to type
679
Tokens
193
Three-star pace
95 tpm

At the three-star pace of 95 tokens a minute, this run takes about 122 seconds.

Type this snippet

Step 3 of 4 in Narrowing, step 9 of 23 in Types & annotations.

← Previous Next →