DEV Community

Rubén Alapont
Rubén Alapont

Posted on

Mastering Indexed Access Types in TypeScript

We should understand the importance of strong typing in our code. TypeScript, with its advanced type system, empowers us to catch errors at compile-time and write more robust applications. One powerful TypeScript feature that often goes underutilized is Indexed Access Types. In this article, we'll dive deep into Indexed Access Types and explore how they can enhance type safety and code readability in your TypeScript projects.

What Are Indexed Access Types?

Indexed Access Types are a way to extract the type of a property from another type using an index signature. This might sound a bit abstract, but it becomes incredibly useful when dealing with complex data structures, such as objects with dynamic keys or arrays of objects.

To understand Indexed Access Types better, let's start with some examples.

Example 1: Accessing Object Properties

Consider an object with dynamic keys, like a configuration object for a set of features:

type FeatureConfig = {
  featureA: boolean;
  featureB: string;
  featureC: number;
};

const config: FeatureConfig = {
  featureA: true,
  featureB: "enabled",
  featureC: 42,
};
Enter fullscreen mode Exit fullscreen mode

Now, if we want to create a type that represents the type of featureA, we can use Indexed Access Types:

type FeatureA = FeatureConfig["featureA"]; // boolean
Enter fullscreen mode Exit fullscreen mode

By using FeatureConfig["featureA"], we extract the type of featureA from the FeatureConfig type. This allows us to access the property's type without explicitly specifying it.

Example 2: Working with Arrays of Objects

Indexed Access Types are particularly handy when dealing with arrays of objects. Consider an array of user objects:

type User = {
  id: number;
  name: string;
  email: string;
};

const users: User[] = [
  { id: 1, name: "Alice", email: "alice@example.com" },
  { id: 2, name: "Bob", email: "bob@example.com" },
  // ...
];
Enter fullscreen mode Exit fullscreen mode

If we want to create a type representing the id property of each user in the array, we can do it like this:

type UserIds = User["id"]; // number
Enter fullscreen mode Exit fullscreen mode

Now, UserIds represents the type of the id property of the User type, which is number.

Using Mapped Types with Indexed Access Types

Indexed Access Types become even more powerful when combined with Mapped Types. Mapped Types allow you to create new types by transforming the properties of an existing type.

Let's say we want to create a type that makes all properties of FeatureConfig optional:

type OptionalFeatureConfig = {
  [K in keyof FeatureConfig]?: FeatureConfig[K];
};
Enter fullscreen mode Exit fullscreen mode

Here, we use keyof FeatureConfig to get a union of all keys in FeatureConfig. Then, we use a mapped type to iterate over these keys and create an optional version of each property. The resulting type, OptionalFeatureConfig, has all properties of FeatureConfig, but each of them is optional.

Conclusion

Indexed Access Types are a valuable tool in TypeScript for working with complex data structures, objects with dynamic keys, and arrays of objects. They allow you to extract the types of specific properties, improving type safety and code readability. When combined with Mapped Types, they enable you to create new types by transforming existing ones.

Top comments (0)