Index signatures and index access types in TypeScript
Index Signatures
An index signature defines the type for dynamic keys in an object when you don't know all property names in advance.
Basic Syntax
typescript
interface StringMap {
[key: string]: string;
}
const translations: StringMap = {
hello: "привіт",
goodbye: "до побачення",
// Any string key with string value is allowed
};
interface NumberMap {
[key: string]: number;
}
const scores: NumberMap = {
math: 95,
english: 88,
};Index Signature with Known Properties
typescript
interface Config {
name: string; // Known property
version: number; // Known property
[key: string]: string | number; // Dynamic properties (must be compatible)
}
const config: Config = {
name: "MyApp",
version: 1,
apiUrl: "https://api.example.com",
timeout: 5000,
};Record vs Index Signature
typescript
// Index signature
interface Dict {
[key: string]: number;
}
// Record utility type (equivalent)
type Dict = Record<string, number>;
// Record with specific keys
type Scores = Record<"math" | "english" | "science", number>;
// { math: number; english: number; science: number }Index Access Types (Lookup Types)
Use T[K] syntax to look up a specific property type:
typescript
interface User {
id: string;
name: string;
email: string;
address: {
city: string;
zip: string;
};
}
type UserId = User["id"]; // string
type UserEmail = User["email"]; // string
type UserAddress = User["address"]; // { city: string; zip: string }
type City = User["address"]["city"]; // string
// Multiple keys
type IdOrEmail = User["id" | "email"]; // stringIndexed Access with Arrays
typescript
const roles = ["admin", "editor", "viewer"] as const;
type Role = typeof roles[number]; // "admin" | "editor" | "viewer"
type FirstRole = typeof roles[0]; // "admin"Dynamic Property Types
typescript
interface ApiResponses {
"/users": { users: User[] };
"/posts": { posts: Post[] };
"/comments": { comments: Comment[] };
}
function fetchData<T extends keyof ApiResponses>(
endpoint: T
): Promise<ApiResponses[T]> {
return fetch(endpoint).then(r => r.json());
}
// Return type is inferred!
const result = await fetchData("/users"); // { users: User[] }keyof with Index Signatures
typescript
interface StringMap {
[key: string]: string;
}
type StringMapKeys = keyof StringMap; // string | number
// (number because JS converts numeric keys to strings)
interface NumberKeyMap {
[key: number]: string;
}
type NumberMapKeys = keyof NumberKeyMap; // numberMapped Types with Index Access
typescript
// Make all properties nullable
type Nullable<T> = {
[K in keyof T]: T[K] | null;
};
type NullableUser = Nullable<User>;
// { id: string | null; name: string | null; ... }Important:
Index signatures define types for dynamic object keys. Index access types (T["key"]) let you extract property types. Combined with keyof, generics, and mapped types, they enable powerful type-safe patterns for APIs, configurations, and data transformations.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.