typestar

Narrowing in TypeScript

The compiler follows your checks: typeof, in, instanceof, truthiness.

type Success = { ok: true; value: string };
type Failure = { ok: false; error: Error };
type Outcome = Success | Failure;

function describe(outcome: Outcome): string {
  if (outcome.ok) return outcome.value.toUpperCase();
  return outcome.error.message;
}

function describeUnion(input: string | number | Date | null): string {
  if (input === null) return "nothing";
  if (typeof input === "string") return input.trim();
  if (typeof input === "number") return input.toFixed(1);
  return input.toISOString();
}

function hasSteps(value: { steps?: number[] } | { slug: string }): boolean {
  return "steps" in value && (value.steps?.length ?? 0) > 0;
}

console.log(describe({ ok: true, value: "done" }));
console.log(describeUnion(new Date(0)), hasSteps({ steps: [1] }));

How it works

  1. in narrows a union by the presence of a property.
  2. instanceof narrows classes; typeof narrows primitives.
  3. A discriminant property is the most readable narrowing of all.

Keywords and builtins used here

The run, in numbers

Lines
22
Characters to type
759
Tokens
212
Three-star pace
95 tpm

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

Type this snippet

Step 2 of 4 in Narrowing, step 8 of 23 in Types & annotations.

← Previous Next →