Records & Index Signatures

An index signature ( { [k: string]: V } ) types an object as a dictionary with any number of keys, while Record<K, V> is the built-in utility for an object whose keys are K and values are V — both are how you give types to key-value maps.

Learn Records & Index Signatures in our free TypeScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.

Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn

💡 Real-World Analogy

Think of a hotel's room-key board. An index signature is a board with unlimited unlabeled hooks: any room number can hang a key (any string key, any value). A Record<union, V> is a board pre-printed with exactly the rooms that exist — every slot is named and must be filled. And noUncheckedIndexedAccess is the honest sign reminding you that reaching for a room that doesn't exist gets you an empty hook (undefined), not a key.

1. Index Signatures: Open Dictionaries

When you don't know the keys in advance — a scores-by-name map, feature flags, a cache — an index signature types it. { [name: string]: number } means "any string key maps to a number." You can read and write any key, iterate with Object.entries , and you can even combine an index signature with a few known fixed properties, as long as their types are compatible.

2. Record<K, V> and keyof

Record<K, V> builds a key-value object type in one expression. With a union of literal keys — Record<"admin" | "user", boolean> — every listed key is required, making it ideal for fixed maps. With Record<string, V> it behaves like an open index signature. The keyof operator pulls the key union back out of any object type.

3. noUncheckedIndexedAccess : Honest Lookups

By default, TypeScript optimistically types a dictionary lookup as the value type — even though, at runtime, a missing key is undefined . That gap causes real "cannot read property of undefined" crashes. The noUncheckedIndexedAccess compiler flag closes it by typing every index access as V | undefined , forcing you to check or default first. It's strongly recommended whenever you work with dictionaries.

🎯 Your Turn

Build a word-count dictionary, defaulting a missing count to 0 . Fill in the blank marked ___ with the right operator, then run it.

Common Errors (and the fix)

Pro Tips

📚 Keep learning

Frequently Asked Questions

Mini-Challenge: groupBy

No blanks this time — just a brief and a starting outline. Build the grouping function yourself, run it, and check your output against the example in the comments.

🎉 Lesson Complete

Practice quiz

What does the index signature '{ [name: string]: number }' describe?

  • An object with exactly one key
  • An array of numbers
  • An object where any string key maps to a number
  • A number named 'name'

Answer: An object where any string key maps to a number. An index signature types an open dictionary: any string key, all values numbers.

What does Record<'admin' | 'user', boolean> require?

  • Exactly the keys admin and user, both present
  • Any string keys
  • At most two keys
  • Only the admin key

Answer: Exactly the keys admin and user, both present. A Record over a union of literal keys requires every listed key to be present.

How does Record<string, number> compare to an index signature?

  • It is stricter
  • It requires all keys
  • It forbids dot access
  • It behaves like an open index signature - any string key

Answer: It behaves like an open index signature - any string key. Record<string, V> is an open dictionary, just like { [k: string]: V }.

What does 'keyof' produce when applied to an object type?

  • The value types
  • A union of the object's keys
  • The number of keys
  • A new object

Answer: A union of the object's keys. keyof Roles for Record<'admin'|'user', boolean> gives 'admin' | 'user'.

With noUncheckedIndexedAccess on, what is the type of a dictionary lookup?

  • V | undefined
  • V
  • unknown
  • never

Answer: V | undefined. The flag makes index access return V | undefined, matching runtime reality.

At runtime, looking up a missing key in an object returns what?

  • null
  • an error
  • undefined
  • an empty object

Answer: undefined. A missing key is always undefined at runtime; the flag makes the type honest.

What is a safe way to read a possibly-missing dictionary value?

Use ?? to provide a default when the key is absent.

Can you combine a known property with an index signature?

  • No, never
  • Only for number keys
  • Only inside a class
  • Yes, if the known property's type is compatible with the index value type

Answer: Yes, if the known property's type is compatible with the index value type. A fixed property is allowed as long as it's assignable to the index signature's value type.

When should you prefer a Map over a typed object dictionary?

  • Always
  • When keys aren't strings, order matters, or you delete entries often
  • For JSON config
  • For string-keyed lookup tables

Answer: When keys aren't strings, order matters, or you delete entries often. Map shines for non-string keys, ordering, frequent inserts/deletes, and a clean size/iteration API.

Which key types are allowed in an index signature?

  • Only string
  • Only number
  • string, number, or symbol
  • Any type

Answer: string, number, or symbol. Index signature keys can be string, number, or symbol.

Continue this course