0Pricing
TypeScript Academy · Lesson

String vs Number Index Signatures

Understand the rules and quirks of numeric keys.

String vs Number Index Signatures is a free TypeScript Academy lesson on CoddyKit — lesson 2 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.

Two Kinds of Index Keys

TypeScript supports both string and number index signatures. They look similar but behave differently because of how JavaScript actually stores object keys.

A Number Index Signature

A number index signature { [i: number]: T } describes objects indexed by numeric position — most naturally, arrays and array-like structures.

type NumberList = { [index: number]: string }

const names: NumberList = { 0: "ana", 1: "leo" }
console.log(names[0]) // ana

JS Coerces Numeric Keys to Strings

Here is the key fact: JavaScript object keys are always strings. When you write obj[0], the engine actually stores the key as the string "0". TypeScript models this reality.

const obj: Record<string, string> = {}
obj[1] = "one"
console.log(obj["1"]) // one — same key!
console.log(Object.keys(obj)) // ["1"]

The Compatibility Rule

Because a numeric key is really a string under the hood, TypeScript enforces a rule: when an object has both a number and a string index signature, the number index's value type must be assignable to the string index's value type.

interface Mixed {
  [key: string]: string
  [index: number]: string // must match the string value type
}
const m: Mixed = { 0: "a", name: "b" }
console.log(m[0], m.name)

Why the Rule Exists

If obj[0] and obj["0"] are the same slot, the value type cannot be a number for one and a string for the other. So the number index value must be a subtype of the string index value to stay consistent.

// This is an ERROR:
// interface Bad {
//   [key: string]: string
//   [index: number]: number // number not assignable to string
// }

Number-Indexed: Arrays

Arrays are the canonical number-indexed type. The built-in Array<T> type effectively has a number index signature, which is why arr[i] gives back T.

const nums: number[] = [10, 20, 30]
const first: number = nums[0]
console.log(first + nums[2]) // 40

Tuples Are Number-Indexed Too

Tuples build on number indexing but pin specific positions to specific types. Out-of-range numeric access falls back to the union of element types or is flagged.

const pair: [string, number] = ["age", 30]
const label: string = pair[0]
const value: number = pair[1]
console.log(label + ": " + value)

String Index Allows Both Lookups

An object with a string index signature still accepts numeric-looking access, because the number is coerced to a string key first.

type Bag = { [key: string]: number }
const b: Bag = {}
b[5] = 100        // stored as key "5"
console.log(b["5"]) // 100

Number Index Does Not Accept Strings

The reverse is not true. An object typed with only a number index signature rejects string keys at compile time, even though JS would technically allow it.

type OnlyNumbers = { [i: number]: string }
const o: OnlyNumbers = { 0: "x" }
// o.name = "y" // Error: property name not on number-indexed type
console.log(o[0])

Choosing Between Them

Use a number index for sequence-like, position-based data (lists, tuples). Use a string index for named lookups (dictionaries, caches). When in doubt, string is the more general choice.

type Positions = { [i: number]: { x: number; y: number } }
type ByName = { [name: string]: { x: number; y: number } }
const p: Positions = { 0: { x: 1, y: 2 } }
console.log(p[0].x)

Practical Mixed Object

You can combine both signatures when a value type works for both — useful for sparse, array-like containers that also expose named slots.

interface Flexible {
  [key: string]: number
  [index: number]: number
}
const f: Flexible = { 0: 1, total: 99 }
console.log(f[0] + f.total) // 100

Quick Check

Test your grasp of string versus number index signatures.

Recap

String and number index signatures differ because JS stores all keys as strings, coercing numbers to string keys. A number index value type must be assignable to the string index value type when both exist. Number indexing models arrays and tuples; string indexing models dictionaries. String-indexed objects accept numeric access, but number-indexed objects reject string keys at compile time.

Frequently asked questions

Is the “String vs Number Index Signatures” lesson free?

Yes — the full text of “String vs Number 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 “String vs Number Index Signatures”?

Understand the rules and quirks of numeric keys. 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 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “String vs Number 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