GGistDev

Control Flow in TypeScript

Core branching and looping constructs, plus TypeScript’s control‑flow based type analysis.

Basics: if/else, switch, loops

const n = 3;
if (n > 0) {
  console.log("positive");
} else if (n === 0) {
  console.log("zero");
} else {
  console.log("negative");
}

const day = "Mon" as const;
switch (day) {
  case "Mon":
  case "Tue":
    console.log("weekday");
    break;
  default:
    console.log("other");
}

for (const x of [1, 2, 3]) console.log(x);    // values
for (const i in { a: 1, b: 2 }) console.log(i); // keys (string)

Prefer for..of for arrays; for..in iterates keys (strings), not values.

Control‑flow narrowing

TypeScript refines types based on checks.

function len(x: string | string[] | null) {
  if (!x) return 0;                    // narrows to string | string[]
  if (typeof x === "string") return x.length;
  return x.length;                      // string[]
}

class A { a = 1 }
class B { b = 2 }
function f(v: A | B) {
  if (v instanceof A) return v.a;      // narrows to A
  return v.b;                          // B
}

function hasId(x: unknown): x is { id: number } {
  return typeof (x as any)?.id === "number";
}

Discriminated unions and exhaustive checks

Use a common literal tag field to discriminate.

type Shape =
  | { kind: "circle"; r: number }
  | { kind: "rect"; w: number; h: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.r ** 2;
    case "rect": return s.w * s.h;
    default: {
      const _exhaustive: never = s; // compile error if a case is missing
      return _exhaustive;
    }
  }
}

Truthiness and nullish values

  • if (x) treats "", 0, NaN, null, undefined as falsy
  • Prefer ?? (nullish coalescing) over || to avoid treating 0/"" as missing
const port = Number(process.env.PORT) ?? 3000;

Try/catch typing

Enable useUnknownInCatchVariables to force safe handling.

try {
  risky();
} catch (e: unknown) {
  if (e instanceof Error) console.error(e.message);
}

Summary

  • Use narrowing (typeof/instanceof/in) and discriminated unions
  • Enforce exhaustiveness with a never check
  • Prefer ?? for defaults; use for..of over arrays