0Pricing
TypeScript Academy · Lesson

Defining Index Signatures

Describe objects whose keys are not known ahead of time.

Defining Index Signatures is a free TypeScript Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Objects with Unknown Keys

Sometimes you do not know the property names in advance — a dictionary of scores, a cache, a lookup table. TypeScript's index signature lets you describe an object whose keys are arbitrary but whose values share one type.

Basic Index Signature Syntax

An index signature is written as { [key: string]: number }. It says: any string key maps to a number value. The name key is just a label — you can call it anything.

type Scores = { [name: string]: number }

const game: Scores = { alice: 10, bob: 7 }
console.log(game.alice) // 10

Adding Keys Dynamically

Because every string key is allowed, you can assign brand-new properties at runtime without TypeScript complaining. This is the whole point of an index signature.

type Scores = { [name: string]: number }

const game: Scores = {}
game.charlie = 5     // allowed
game["dave"] = 9     // also allowed
console.log(game.charlie + game.dave) // 14

Accessing Arbitrary Keys

You can read any key, even one that was never set. The type system trusts the signature, so the value type is number — but at runtime a missing key is undefined. Be careful.

type Scores = { [name: string]: number }

const game: Scores = { alice: 10 }
const missing = game.zara // typed as number, but actually undefined
console.log(missing) // undefined

All Values Must Conform

Every property in the object must match the value type of the signature. You cannot mix a number value into a string-valued dictionary.

type Labels = { [key: string]: string }

const ok: Labels = { id: "a1", role: "admin" }
// const bad: Labels = { id: "a1", count: 5 } // Error: 5 not a string

Index Signatures in Interfaces

The same syntax works inside an interface. This is common for describing config bags or response maps from an API.

interface Dictionary {
  [word: string]: string
}

const defs: Dictionary = {
  cat: "a small animal",
  ts: "a typed superset of JavaScript",
}
console.log(defs.ts)

Value Types Can Be Anything

The value side is not limited to primitives. You can map keys to arrays, objects, or unions — whatever your data needs.

type Groups = { [team: string]: string[] }

const roster: Groups = {
  red: ["ana", "leo"],
  blue: ["sam"],
}
console.log(roster.red.length) // 2

Iterating Index-Signature Objects

A for...in loop visits each dynamic key. Inside the loop the value is correctly typed according to the signature.

type Scores = { [name: string]: number }
const game: Scores = { alice: 10, bob: 7 }

for (const name in game) {
  console.log(name + ": " + game[name])
}

The undefined Safety Gap

Index signatures hide the fact that lookups can fail. Enabling noUncheckedIndexedAccess in tsconfig adds | undefined to every access, forcing you to handle missing keys.

// with noUncheckedIndexedAccess on:
type Scores = { [name: string]: number }
const game: Scores = { alice: 10 }
const v = game.bob // type: number | undefined
console.log(v ?? 0)

Readonly Index Signatures

Prefix the signature with readonly to forbid writing through any key. The dictionary becomes a lookup-only structure.

type Frozen = { readonly [key: string]: number }

const rates: Frozen = { usd: 1, eur: 1.1 }
// rates.usd = 2 // Error: read-only
console.log(rates.eur)

When Index Signatures Shine

Reach for an index signature when the set of keys is open-ended and discovered at runtime: caches, counters keyed by id, parsed query params. For a fixed, known key set, prefer explicit properties or Record.

type Counter = { [event: string]: number }
const clicks: Counter = {}
function track(e: string) { clicks[e] = (clicks[e] ?? 0) + 1 }
track("open"); track("open")
console.log(clicks.open) // 2

Quick Check

Test your understanding of index signatures.

Recap

You learned that { [key: string]: T } describes objects with arbitrary keys whose values all share type T. Keys can be added dynamically, every value must conform to the signature, and lookups of missing keys are undefined at runtime. Use readonly for immutable maps and enable noUncheckedIndexedAccess for safer access.

Frequently asked questions

Is the “Defining Index Signatures” lesson free?

Yes — the full text of “Defining Index Signatures” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Defining Index Signatures”?

Describe objects whose keys are not known ahead of time. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start TypeScript Academy?

No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Defining Index Signatures” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this TypeScript Academy lesson?

Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Defining Index Signatures
  2. String vs Number Index Signatures
  3. Combining Known and Dynamic Keys
  4. Index Signatures vs Record
← Back to TypeScript Academy