Index signatures
๐ What are Index Signatures in TypeScript? When you need an object that can have any number of string keys all mapping to the same value type -- like a dictionary -- you use an index signature: { [key: string]: number }. This says: 'this object can have any string as a key, and every value will beโฆ

Appy Saysโฆ
Sometimes you don't know the exact property names ahead of time โ you just know they'll all be strings mapping to numbers, or strings mapping to strings. Index signatures let you type these dynamic objects.
What are Index Signatures?
An index signature describes objects with dynamic keys โ you specify the key type and value type, without listing every property name.
- โขSyntax:
{ [key: string]: ValueType } - โข
interface StringMap { [key: string]: string; } - โข
const headers: StringMap = { 'Content-Type': 'application/json' }; - โขIndex signature means ANY string key maps to that type
- โขCan combine with specific properties:
{ id: number; [key: string]: string | number; } - โขRecord type (cleaner alternative):
Record<string, string>โ same as index signature
Think of it like a Minecraft chest that holds only diamonds
You don't know what's in every slot โ slots are dynamic. But you know every slot either has diamonds or is empty. An index signature types this: 'I don't know the keys, but every value is a diamond (the declared type)'.
How It Works
- โข1.
interface Config { [key: string]: string | number; } - โข2.
const c: Config = { host: 'localhost', port: 3000 }; - โข3. TypeScript allows any string key, but value must be string | number
- โข4. Accessing:
c['host']โstring | number - โข5. Record shorthand:
type Config = Record<string, string | number>; - โข6. Number keys:
{ [index: number]: string }โ like arrays
Real-World Examples
- โขHTTP headers:
Record<string, string> - โขTranslation map:
Record<string, string>โ key=locale ID, value=translated text - โขScore board:
Record<string, number>โ key=player name, value=score - โขCSS variables:
Record<string, string>โ key=var name, value=colour
Key Facts
- โข
Record<K, V>is shorthand for an index signature:{ [key in K]: V } - โขIndex signatures allow all string keys โ TypeScript can't narrow a specific key's type
- โขFor known keys, use a proper interface or object type literal instead
- โขWhen you access a Record value TypeScript returns T | undefined with noUncheckedIndexedAccess โ use that config option for safer access
Watch Out!
Index signatures are looser than typed interfaces โ TypeScript allows any string key so you lose specific property guarantees. If you know all the keys, use a proper typed interface: { name: string; age: number; } is safer than Record<string, string | number>.
Remember
{ [key: string]: ValueType } or Record<string, ValueType> โ types objects with dynamic keys. Use when you genuinely don't know the keys ahead of time. Prefer explicit interfaces when keys are known.
What You Learned
- โขIndex signatures type dynamic-key objects:
{ [key: string]: Type }or Record - โขAny string key is allowed; value type is enforced
- โขUnlocks: HTTP headers, score maps, translation dictionaries, any key-value store
Key Facts
- โ
Record<K, V>is shorthand for an index signature:{ [key in K]: V } - โIndex signatures allow all string keys โ TypeScript can't narrow a specific key's type
- โFor known keys, use a proper interface or object type literal instead
- โWhen you access a Record value TypeScript returns T | undefined with noUncheckedIndexedAccess โ use that config option for safer access
Real-World Examples
Remember
{ [key: string]: ValueType } or Record<string, ValueType> โ types objects with dynamic keys. Use when you genuinely don't know the keys ahead of time. Prefer explicit interfaces when keys are known.
Quick Quiz
[key: string]: number means?