Loading lesson path
Concept visual
Index signatures in TypeScript provide a powerful way to define types for objects with dynamic property names while maintaining type safety. They allow you to specify the types of values that can be accessed via bracket notation ( obj[key] ), even when the exact property names aren't known in advance.
: Handle objects with arbitrary property names
: Ensure consistent value types across dynamic properties
: Model dictionaries, maps, and other dynamic data
Formula
: Catch type - related errors at compile timeIndex signatures in TypeScript allow you to define types for objects where you don't know the property names in advance, but you do know the shape of the values. An index signature defines the types for properties accessed via an index like obj[key].
// This interface represents an object with string keys and string values interface StringDictionary {
[key: string]: string;
}
// Creating a compliant object const names: StringDictionary = {
firstName: "Alice", lastName: "Smith",
"100": "One Hundred"
};
// Accessing properties console.log(names["firstName"]); // "Alice"
console.log(names["lastName"]); // "Smith"
console.log(names["100"]); // "One Hundred"
// Adding new properties dynamically names["age"] = "30";// This would cause an error
// names["age"] = 30; // Error: Type 'number' is not assignable to type 'string'[key: type] to describe the types of the property names (or keys) that are allowed, followed by the type of values these properties can have.
TypeScript supports both string and number index signatures:
// Object with number indexes interface NumberDictionary {
[index: number]: any;
}
const scores: NumberDictionary = {
0: "Zero",1: 100, 2: true
};
console.log(scores[0]); // "Zero"
console.log(scores[1]); // 100 console.log(scores[2]); // true
// Adding a complex object scores[3] = { passed: true };In JavaScript, all object keys are stored as strings, even numeric ones. However, TypeScript makes a distinction to help catch logical errors when using arrays vs objects.
You can combine index signatures with explicit property declarations:
Example interface UserInfo {
name: string; // Required property with specific name age: number; // Required property with specific name
[key: string]: string | number; // All other properties must be string or number
}
const user: UserInfo = {
name: "Alice", // Required age: 30, // Required address: "123 Main St", // Optional zipCode: 12345 // Optional
};// This would cause an error
// const invalidUser: UserInfo = {
// name: "Bob",
// age: "thirty", // Error: Type 'string' is not assignable to type 'number'
// isAdmin: true // Error: Type 'boolean' is not assignable to type 'string | number'
// };When combining explicit properties with an index signature, the types of explicit properties must be assignable to the index signature's value type.
Formula
You can make index signatures read - only to prevent modification after creation:Example interface ReadOnlyStringArray {
readonly [index: number]: string;
}
const names: ReadOnlyStringArray = ["Alice", "Bob", "Charlie"];
console.log(names[0]); // "Alice"// This would cause an error
// names[0] = "Andrew"; // Error: Index signature in type 'ReadOnlyStringArray' only permits readingFor constraining key sets and transforming shapes, see Mapped Types.
// Type for API responses with dynamic keys interface ApiResponse<T> {
data: {
[resourceType: string]: T[]; // e.g., { "users": User[], "posts": Post[] }
};
meta: {
page: number;
total: number;
[key: string]: any; // Allow additional metadata
};
}// Example usage with a users API
interface User {
id: number;
name: string;
email: string;
}Formula
// Mock API response const apiResponse: ApiResponse < User > = {data: {
users: [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" }]
}, meta: {Formula
page: 1, total: 2, timestamp: "2023 - 01 - 01T00:00:00Z"}
};
// Accessing the data const users = apiResponse.data.users;
console.log(users[0].name); // "Alice"Use index signatures for collections with dynamic keys
Keep value types specific (avoid any )