obj["key"]). In TypeScript, Indexed Access Types (T[K]) allow you to look up the exact type of a property, array element, or tuple index using the exact same bracket syntax at the type level.1. The T[K] Lookup Syntax#
Instead of manually duplicating nested type definitions, you can look up a property type directly from an existing interface:
interface UserAccount {
id: string;
profile: {
displayName: string;
avatarUrl: string;
bio: string;
};
settings: {
theme: "light" | "dark" | "system";
notificationsEnabled: boolean;
};
}
// 🟢 Extract the 'profile' property type directly:
type UserProfile = UserAccount["profile"];
/* Inferred Type:
{
displayName: string;
avatarUrl: string;
bio: string;
}
*/
// 🟢 Extract the 'theme' property type directly (Nested Indexing):
type ThemeSetting = UserAccount["settings"]["theme"];
// Inferred Type: "light" | "dark" | "system"
The Index Constraint Rule (K extends keyof T)#
The key used inside the bracket index must be a valid property key of the target type. If you attempt to index with a key that does not exist on T, TypeScript throws a compile-time error:
// ❌ Compiler Error: Property 'password' does not exist on type 'UserAccount'.
// type PasswordType = UserAccount["password"];
2. Union Indexing (T["a" | "b"])#
You can pass a Union of Keys as the index parameter to extract a Union of Property Types simultaneously:
interface CustomerPayload {
id: string;
age: number;
isVIP: boolean;
registeredAt: Date;
}
// Look up types for 'id' AND 'age' simultaneously:
type IdOrAge = CustomerPayload["id" | "age"];
// Inferred Type: string | number
// Look up types for ALL properties by passing 'keyof CustomerPayload':
type AllCustomerValues = CustomerPayload[keyof CustomerPayload];
// Inferred Type: string | number | boolean | Date
3. Array Element Indexing (ArrayType[number])#
To extract the type of elements stored inside an array or list, index the array type using the JavaScript keyword number:
interface Order {
orderId: string;
items: Array<{
sku: string;
quantity: number;
price: number;
}>;
}
// 🟢 Extract the type of a SINGLE item inside the 'items' array:
type OrderItem = Order["items"][number];
/* Inferred Type:
{
sku: string;
quantity: number;
price: number;
}
*/How ArrayType[number] Works#
Because array elements are accessed via numeric indices (arr[0], arr[1], …), passing the type number as the index tells TypeScript: “Look up the union of all types accessible via any numeric index.”
4. Tuple Indexing (Tuple[0], Tuple[number])#
Tuples support both specific numeric index lookups and union element lookups:
type HttpResponse = [statusCode: number, message: string, headers: Record<string, string>];
// 1. Look up element at index 0:
type StatusCode = HttpResponse[0]; // Inferred Type: number
// 2. Look up element at index 1:
type Message = HttpResponse[1]; // Inferred Type: string
// 3. Look up ALL possible tuple element types:
type TupleElements = HttpResponse[number];
// Inferred Type: number | string | Record<string, string>
5. Architectural Pattern: Single Source of Truth (DRY Types)#
Indexed access types eliminate redundant interface declarations and ensure that updating a core domain model automatically cascades type updates across all dependent utility functions.
// 1. Core Domain API Contract (Single Source of Truth)
export interface EventPayload {
eventId: string;
metadata: {
ip: string;
userAgent: string;
};
payload: {
action: "CLICK" | "SCROLL" | "SUBMIT";
timestamp: number;
};
}
// 2. Utility functions extract EXACT sub-types without copy-pasting definitions!
function logMetadata(meta: EventPayload["metadata"]) {
console.log(`[IP]: ${meta.ip}, [UA]: ${meta.userAgent}`);
}
function processAction(action: EventPayload["payload"]["action"]) {
console.log(`Executing Action: ${action}`);
}If the core EventPayload interface is later updated (e.g. adding "HOVER" to action), processAction() updates its parameter type automatically without manual refactoring!
Summary & Next Steps#
In this episode:
- We learned the syntax and constraint rules of Indexed Access Types (
T[K]). - We performed nested lookups (
T["a"]["b"]) and union lookups (T["a" | "b"]). - We extracted array element types using
ArrayType[number]. - We indexed tuples using specific numeric literals (
Tuple[0]) andTuple[number]. - We built a DRY domain model architecture using single-source-of-truth indexing.
In Episode 27: The keyof Operator, we will learn how to extract object keys as string literal unions!

