Jiaxi Liu (Jesse)

Master’s Graduate

Software Engineer | Scalable APIs · Web Scraping · Data Integration · Code Quality & Refactoring

Back to Blog

TypeScript Control Flow, Record Dictionaries, and Array Iteration: for, for...of, for...in, forEach, and map

This note answers a practical question: when working with objects, arrays, dictionaries, and loops, which syntax should you use and why?

?? vs ||

?? uses the fallback only when the value is null or undefined.

const value = input ?? "default";

|| uses the fallback for any falsy value, including false, 0, "", NaN, null, and undefined.

const page = query.page || 1;

If 0 is a valid value, avoid ||.

const discount = userDiscount ?? 0;

Record Dictionaries

Record<K, V> describes a key-value map.

const userAges: Record<string, number> = {
  Alice: 25,
  Bob: 30,
};

If keys are a fixed set, use a union type.

type Role = "admin" | "editor" | "viewer";
 
const permissions: Record<Role, string[]> = {
  admin: ["read", "write", "delete"],
  editor: ["read", "write"],
  viewer: ["read"],
};

This is safer than Record<string, string[]> because missing roles become compile errors.

Index Signatures

Index signatures are useful when keys are fully dynamic.

interface ScoreMap {
  [name: string]: number;
}
 
const scores: ScoreMap = {};
scores.Alice = 95;

The tradeoff is that any string key is allowed.

Choosing a Loop

Use for when you need an index, early exit, or precise loop control.

for (let i = 0; i < items.length; i++) {
  if (items[i] === target) break;
}

Use for...of when you want values from arrays, strings, Sets, or other iterables.

for (const fruit of fruits) {
  console.log(fruit);
}

Use for...in for object keys, but guard against inherited properties.

for (const key in person) {
  if (Object.prototype.hasOwnProperty.call(person, key)) {
    console.log(key, person[key as keyof typeof person]);
  }
}

forEach vs map

forEach is for side effects and does not return a new array.

numbers.forEach((num) => {
  console.log(num);
});

map transforms an array and returns a new one.

const doubled = numbers.map((num) => num * 2);

Simple rules:

  • Need a new array: map
  • Need filtering: filter
  • Need accumulation: reduce
  • Logging or side effects: forEach
  • Need break or continue: for...of or for