Index Signatures

Objects with Unknown Keys

When you do not know the property names in advance (a dictionary or map), use an index signature: { [key: string]: number }. Record<string, number> is a shorter way to write the same.

Example

const stockBySku: { [sku: string]: number } = {
  "SKU-101": 40,
  "SKU-205": 0,
};
stockBySku["SKU-310"] = 15;

const ratings: Record<string, number> = { Books: 4.5, Fashion: 4.1 };

for (const [sku, qty] of Object.entries(stockBySku)) {
  console.log(sku, qty > 0 ? "in stock" : "sold out");
}
console.log(ratings["Books"]);

Output

SKU-101 in stock
SKU-205 sold out
SKU-310 in stock
4.5

Missing Keys are undefined

Example

By default TypeScript assumes every key exists, so stock["X"] is typed as number even though it is undefined at runtime. The noUncheckedIndexedAccess option (advanced level) fixes this. Until then, check with in or ??.

const stock: Record<string, number> = { "SKU-101": 40 };

const unsafe = stock["SKU-999"];
console.log(unsafe);

const safe = stock["SKU-999"] ?? 0;
console.log(safe, "SKU-999" in stock);

Output

undefined
0 false

Practice

Exercise: Create a type MarksSheet where keys are subject names and values are marks. Write a function that returns the average.

Show answer
type MarksSheet = { [subject: string]: number };

function average(sheet: MarksSheet): number {
  const values = Object.values(sheet);
  return values.reduce((a, b) => a + b, 0) / values.length;
}

console.log(average({ Maths: 90, Physics: 80, English: 70 })); // 80