Menu
×
   ❮   
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING BASH RUST

TypeScript Index Signatures


Understanding Index Signatures in TypeScript

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.


Key Concepts

  • Dynamic Property Access: Handle objects with arbitrary property names
  • Type Safety: Ensure consistent value types across dynamic properties
  • Flexible Data Structures: Model dictionaries, maps, and other dynamic data
  • Runtime Safety: Catch type-related errors at compile time

Basic Index Signatures

String Index Signatures

Index 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].

Example

// 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'
Try it Yourself »

The index signature syntax uses brackets [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.



Number Index Signatures

TypeScript supports both string and number index signatures:

Example

// 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 };
Try it Yourself »

Note: 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.


Advanced Index Signature Patterns

Mixed Property Types

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'
// };
Try it Yourself »

Important: When combining explicit properties with an index signature, the types of explicit properties must be assignable to the index signature's value type.


ReadOnly Index Signatures

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 reading
Try it Yourself »

For constraining key sets and transforming shapes, see Mapped Types.


Real-World Examples

API Response Handling

Example

// 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;
}

// 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: {
    page: 1,
    total: 2,
    timestamp: "2023-01-01T00:00:00Z"
  }
};

// Accessing the data
const users = apiResponse.data.users;
console.log(users[0].name);  // "Alice"
Try it Yourself »

Best Practices

Do's and Don'ts

Do:

  • Use index signatures for collections with dynamic keys
  • Combine with explicit properties for known fields
  • Keep value types specific (avoid any)
  • Use readonly when mutation isn't needed

Don't:

  • Prefer fixed interfaces when keys are known
  • Forget that all properties must conform to the index signature type
  • Reinvent mapped types—use the dedicated page for transformations

Common Pitfalls

Property Name Conflicts

interface ConflictingTypes {
  [key: string]: number;
  name: string; // Error: not assignable to string index type 'number'
}

interface FixedTypes {
  [key: string]: number | string;
  name: string;  // OK
  age: number;   // OK
}

Index Signatures vs. Record<K, T>

Use an index signature for flexible/dynamic keys and when mixing with other properties.

Use Record<K, T> for concise simple mappings.

// Index signature
interface StringMap {
  [key: string]: string;
}

// Record
type StringRecord = Record<string, string>;

Conclusion

Use index signatures when keys are dynamic but value shapes are consistent.

Combine with explicit properties where possible, and see Mapped Types and Utility Types for advanced transformations.




×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2025 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.