TypeScript Tutorial · TypeScript Basics · Lesson 5 of 25

TypeScript Index Signatures and Records

Type objects used as dictionaries with index signatures and Record.

Dictionaries

When an object's keys aren't known in advance — a lookup table, word counts, a cache — describe it with an index signature or Record:

Example 1Try it yourself
const wordCounts: { [word: string]: number } = {};
for (const w of "the cat and the hat".split(" ")) {
  wordCounts[w] = (wordCounts[w] ?? 0) + 1;
}
console.log(wordCounts);

const cache: Record<string, string> = {};
cache["/home"] = "<html>...</html>";
console.log(Object.keys(cache));

Output

{ the: 2, cat: 1, and: 1, hat: 1 }
[ '/home' ]

Record<K, V> is shorthand for { [key in K]: V }. With a union of literal keys, it forces you to provide every key:

Example 2Try it yourself
type Env = "dev" | "staging" | "prod";
const apiUrl: Record<Env, string> = {
  dev: "http://localhost:8000",
  staging: "https://staging.example.com",
  prod: "https://api.example.com",
};
// @ts-expect-error — Property 'prod' is missing in type.
const incomplete: Record<Env, string> = { dev: "x", staging: "y" };
console.log(apiUrl.prod, Object.keys(incomplete).length);

Output

https://api.example.com 2

For dictionaries that change at runtime, a Map<K, V> is often the better choice.

Test yourself

What does Record<"a" | "b", number> require?

  1. An object with key a or b
  2. An object with both keys a and b, each a number
  3. An array of numbers
  4. A Map
Show answer

Answer: An object with both keys a and b, each a number