🧠 TypeScript β€” Indexed Access Types: Complete Guide with Examples

🧲 Introduction – Why Use Indexed Access Types?

In TypeScript, Indexed Access Types allow you to reference the type of a specific property from another type. This powerful mechanism promotes type reusability, accuracy, and type safetyβ€”especially useful when working with complex objects, generics, or deeply nested types.

🎯 What You’ll Learn:

  • What indexed access types are
  • How to use them with keys, unions, arrays, and generics
  • Detailed explanations for every code snippet
  • Real-world usage patterns

πŸ“˜ What Are Indexed Access Types?

Indexed Access Types let you dynamically reference a type of a property using its key:

type PropertyType = TypeName[Key];
  • TypeName: any object type (e.g., interface, type alias)
  • Key: the name of a property in the object type

πŸ§ͺ Example 1: Extracting a Property Type

type User = {
  name: string;
  age: number;
};

type NameType = User["name"]; // string
type AgeType = User["age"];   // number

πŸ” Explanation:

  • User is a type with two properties: name (string) and age (number).
  • User["name"] accesses the type of the name property β€” which is string.
  • User["age"] accesses the type of the age property β€” which is number.

You don’t need to repeat the structure manually. This ensures automatic consistency with the User type.


πŸ” Example 2: Using keyof with Indexed Access Types

type UserKeys = keyof User;         // "name" | "age"
type ValueTypes = User[UserKeys];   // string | number

πŸ” Explanation:

  • keyof User returns a union of all keys: "name" | "age".
  • User[UserKeys] means we’re accessing both User["name"] and User["age"] β€” resulting in a union of their types: string | number.

This is how you extract all value types from an object type dynamically.


πŸ”— Example 3: Indexing with Union of Keys

type Person = {
  id: number;
  name: string;
  active: boolean;
};

type IdOrStatus = Person["id" | "active"]; // number | boolean

πŸ” Explanation:

  • You’re accessing two properties at once: id (number) and active (boolean).
  • The result is a union: number | boolean.

βœ… This pattern is useful when extracting specific subsets of property types.


πŸ”„ Example 4: Indexed Access with Arrays

type Roles = ["admin", "user", "guest"];
type Role = Roles[number]; // "admin" | "user" | "guest"

πŸ” Explanation:

  • Roles is a tuple (fixed-length array) with three string literals.
  • Using Roles[number] means we’re asking: β€œWhat is the type of any element in Roles?”
  • Since it’s a union of all possible index values (0, 1, 2), the result is "admin" | "user" | "guest".

πŸ“Œ This is commonly used for defining value enums or dropdown options.


🧰 Example 5: Type-Safe Property Accessor Function

function getValue<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

const product = { id: 101, name: "Notebook", price: 500 };
const id = getValue(product, "id");     // number
const name = getValue(product, "name"); // string

πŸ” Explanation:

  • T is a generic type representing any object.
  • K extends keyof T ensures that key must be a valid property of T.
  • T[K] dynamically returns the type of that property.

This prevents typos and incorrect property access during development.


πŸ” Example 6: Nested Indexed Access Types

type Profile = {
  user: {
    name: string;
    contact: {
      email: string;
      phone: string;
    };
  };
};

type ContactType = Profile["user"]["contact"]; // { email: string; phone: string }
type EmailType = Profile["user"]["contact"]["email"]; // string

πŸ” Explanation:

  • You’re chaining property access to go deep inside nested objects.
  • Profile["user"] gives you the type of the user object.
  • Adding another layer: ["contact"], and then ["email"] gives the final string type.

βœ… This is particularly useful when working with API response types or configuration schemas.


πŸ§ͺ Example 7: With Mapped Types & keyof

type Car = {
  brand: string;
  year: number;
};

type CarProperties = {
  [K in keyof Car]: Car[K];
};

πŸ” Explanation:

  • This is a mapped type.
  • For each key in Car, we get its type via Car[K] using indexed access.
  • The result is effectively the same as the original Car type.

πŸ“Œ This pattern is how many built-in utility types (like Pick, Record, Partial) work.


βœ… Best Practices for Indexed Access Types

  • πŸ’‘ Use with generics: Great for reusable functions.
  • πŸ” Avoid repetition: DRY your types by referencing them instead of rewriting.
  • πŸ›‘οΈ Type safety: Reduces runtime errors from invalid property access.

πŸ“Œ Summary – Recap & Use Cases

Indexed access types are a foundational feature of TypeScript that allows developers to look up property types dynamically. Whether you’re working with generics, APIs, or arrays, this approach ensures better scalability and type integrity.

πŸ” Key Takeaways:

  • Use Type["key"] to extract the type of a property
  • Combine with keyof to iterate through keys
  • Supports deep indexing and union keys
  • Widely used in utility types, schema validation, and component props

βš™οΈ Real-World Scenarios:

  • Extracting data from deeply nested API responses
  • Validating form fields based on object structure
  • Creating reusable, safe dynamic functions

❓ FAQs

❓ What is the difference between typeof and indexed access types?

FeaturetypeofIndexed Access Type
PurposeExtracts type from a valueExtracts type from a property
Usagetypeof someValueSomeType["property"]
Exampletypeof userUser["name"]

❓ Can indexed access types work with tuples and arrays?

βœ… Yes! Use numeric keys:

type MyTuple = [string, number];
type First = MyTuple[0]; // string
type Second = MyTuple[1]; // number

❓ Do utility types in TypeScript use indexed access?

βœ… Absolutely! Built-in types like Pick<T, K> and Record<K, T> heavily rely on this feature under the hood.


❓ Is it safe to use nested indexed types?

βœ… Yes, and it’s encouraged for API-heavy or config-heavy applications. Just ensure the path exists, or combine with optional chaining types (?. for runtime, Partial for types).


Share Now :
Share

TypeScript β€” Indexed Access Types

Or Copy Link

CONTENTS
Scroll to Top