🧠 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 :

Leave a Reply

Your email address will not be published. Required fields are marked *

Share

TypeScript — Indexed Access Types

Or Copy Link

CONTENTS
Scroll to Top