Indexed Access Types (or index access types) allow referring to the type of a specific property of an object or any key through the syntax T[K]. This is a powerful tool for creating flexible and type-safe abstractions.
type Person = { name: string; age: number; }; type NameType = Person['name']; // string type AgeOrName = Person['age' | 'name']; // number | string
Used for writing generic types and functions:
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; // correct return type } const user = { email: 'a@a.ru', id: 1 }; let id = getProperty(user, 'id'); // id: number
Person['salary'] – a compile-time error.Question: What type will the expression type Foo = {a: number, b: string}["a" | "b" | "c"] produce?
Answer: This example will cause a compile error because 'c' is not a key in the type being accessed. TypeScript will throw the error:
Type '"c"' does not satisfy the constraint '"a" | "b"'.
Story
In the project, forms were dynamically generated based on types. After adding a new field to the main type, the indexed access locations weren't updated, and as a result, some properties did not make it into the form, although a complete mapping was expected at the type level. The error only manifested at runtime, not at development time.
Story
In a data validation library, indexed access was used through types, but when migrating the code, one of the keys was moved from the object to the parent. The old indexed type led to a compile error; however, the error only arose after rebuilding due to CI caching, and before that, it lived on staging for several weeks.
Story
It was mistakenly believed that Indexed Access Types could be used to access any key, even if it was not explicitly listed, which led to incorrect auto-test generation for dynamic properties. As a result, tests did not cover part of the possible scenarios as the compiler threw these cases as invalid.