---
title: Bitovi Academy - Index Accessed Types
description: Learn how to look up types of properties with index accessed types!
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting?hsLang=en-us)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting?hsLang=en-us)
- ![Project management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project management](https://www.bitovi.com/services/agile-project-management-consulting?hsLang=en-us)
- ![Product design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product design](https://www.bitovi.com/services/product-design-consulting?hsLang=en-us)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services?hsLang=en-us)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting?hsLang=en-us)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers?hsLang=en-us)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting?hsLang=en-us)
- [Design Systems](https://www.bitovi.com/services/axure-figma-migration?hsLang=en-us)
- [React](https://www.bitovi.com/services/frontend/react-consulting?hsLang=en-us)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting?hsLang=en-us)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native?hsLang=en-us)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting-1?hsLang=en-us)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study?hsLang=en-us)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign?hsLang=en-us)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work?hsLang=en-us)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source?hsLang=en-us)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about perfecting software delivery
  
  ](https://bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships?hsLang=en-us)
- [![Academy](https://www.bitovi.com/hubfs/limbo/icons/icon-academy.svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy/?hsLang=en-us)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse our tools or contribute to our open source mission.
  
  ](https://www.bitovi.com/open-source?hsLang=en-us)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

- [ Advanced JavaScript ](https://www.bitovi.com/academy/learn-advanced-javascript.html?hsLang=en-us)
- [ DOM and jQuery ](https://www.bitovi.com/academy/learn-dom-jquery.html?hsLang=en-us)
- [ Debug JavaScript ](https://www.bitovi.com/academy/learn-to-debug-javascript.html?hsLang=en-us)
- [ Learn TypeScript ](https://www.bitovi.com/academy/learn-typescript.html?hsLang=en-us)
- [ Learn React Native ](https://www.bitovi.com/academy/learn-react-native.html?hsLang=en-us)
- [ Learn Web Components ](https://www.bitovi.com/academy/learn-web-components.html?hsLang=en-us)
- [ Agile Program Management With Jira ](https://www.bitovi.com/academy/learn-agile-program-management-with-jira.html?hsLang=en-us)
- [ Learn RxJS ](https://www.bitovi.com/academy/learn-rxjs.html?hsLang=en-us)
- [ Giving a Training ](https://www.bitovi.com/academy/training.html?hsLang=en-us)
- [ Learn Technology Consulting ](https://www.bitovi.com/academy/learn-technology-consulting.html?hsLang=en-us)
- [ Learn React ](https://www.bitovi.com/academy/learn-react.html?hsLang=en-us)
- [ Learn NgRx ](https://www.bitovi.com/academy/learn-ngrx.html?hsLang=en-us)
- [ Learn Graphql ](https://www.bitovi.com/academy/learn-graphql.html?hsLang=en-us)
- [ Learn Docker ](https://www.bitovi.com/academy/learn-docker.html?hsLang=en-us)
- [ Learn CanJS ](https://www.bitovi.com/academy/learn-canjs.html?hsLang=en-us)
- [ Learn Angular ](https://www.bitovi.com/academy/learn-angular.html?hsLang=en-us)
- [ Advanced TypeScript ](https://www.bitovi.com/academy/advanced-typescript.html?hsLang=en-us) 
    - [ Typing Systems ](https://www.bitovi.com/academy/advanced-typescript/typing-systems.html?hsLang=en-us)
    - [ Generics With Constraints ](https://www.bitovi.com/academy/advanced-typescript/generics-with-constraints.html?hsLang=en-us)
    - [ Index Accessed Types ](https://www.bitovi.com/academy/advanced-typescript/index-accessed-types.html?hsLang=en-us)
    - [ Mapped Types ](https://www.bitovi.com/academy/advanced-typescript/mapped-types.html?hsLang=en-us)
    - [ Conditional Types ](https://www.bitovi.com/academy/advanced-typescript/conditional-types.html?hsLang=en-us)
    - [ Template Literal Types ](https://www.bitovi.com/academy/advanced-typescript/template-literal-types.html?hsLang=en-us)

[View More Courses](https://www.bitovi.com/academy/#courses) [ ]

# Index Accessed Types `page`

Learn how to look up types of properties with index accessed types!

## Overview

There are many times we would like to forego defining a type and rather use some other type as a reference instead. Index Accessed Types is a TypeScript feature that allows us to do just that! In this section, we will look at index accessed types, how they work, and how they are defined. Towards the end we will see a practical application!

## Index Accessed Types

Index accessed types are a way to look up types on other types. TypeScript uses square bracket notation (`[]`) to grab the desired type off of object types, much like how you can access a specific property from a JavaScript object using square brackets (`someObject["someKey"]`).

```
type Pokemon = {
  power: number;
  name: string;
  type: "fire" | "water" | "grass";
  ///...
};

type PokemonName = Pokemon["name"]; // string
type PokemonPower = Pokemon["power"]; // number
type PokemonTypes = Pokemon["type"]; // "fire" | "water" | "grass"
```

In the example above `'name'`, `'power'`, and `'type'` are not strings, but types (literal types). Index access types can only be used with types. Any value provided will produce an error.

```
const name = "name";
type PokemonNameFail = Pokemon[name]; // 'name' refers to a value, but is being used as a type here.
type PokemonNameWithTypeOf = Pokemon[typeof name]; // string;

type Name = "name";
type PokemonNameWithLiteralType = Pokemon[Name]; // string
```

If the type provided is not able to index a particular type, TypeScript will provide an error.

```
type Pokemon = {
  power: number;
  name: string;
  type: "fire" | "water" | "grass";
  ///...
};

// ERROR: Property 'invalidKey' does not exist on type 'Pokemon'.
type InvalidExample1 = Pokemon["invalidKey"];

type GymLeader = {
  name: string;
  location: string;
  typeOfGym: "fire" | "water" | "earth";
};

// ERROR: Type 'GymLeader' cannot be used as an index type.
type InvalidExample2 = Pokemon[GymLeader];
```

### Multiple Types as Indices

When TypeScript sees more than one type being passed in it will create a union of the property types — `keyof` and string unions illustrate this.

```
type PokemonTypeOrPower = Pokemon["power" | "type"]; // number | "fire" | "water" | "grass"

type PokemonPropertyValues = Pokemon[keyof Pokemon]; // string | number;
```

> It might be surprising to see that `Pokemon[keyof Pokemon]` is `string | number` and not `string | number | "fire" | "water" | "grass"`. This happens because the value constraints of the string literal union do not have any impact on the newly formed type. The type `"fire" | "water" | "grass"` is a subset of `string` meaning any `string` provided to `string | number | "fire" | "water" | "grass"` will pass. TypeScript knows this and purposely omits the union for clarity.

Index access types are chainable, this allows us to access as deep a property as we would like simply by adding more brackets.

```
type PokemonMove = {
  name: string;
  description: string;
  pp: number;
};

type Pokemon = {
  power: number;
  name: string;
  type: "fire" | "water" | "grass";
  firstMove: PokemonMove;
};

type PokemonMoveName = Pokemon["firstMove"]["name"]; // string
```

### With Generics

Index accessed types also work with generics, let’s take a look at an example they may seem familiar if you did the exercises from the last section

```
function getStarterPokemonInfomation<Starters, Name extends keyof Starters>(
  starter: Starters,
  name: Name
) {
  return starter[name];
}
```

In this exercise we didn’t define the return type of this function; instead opting for TypeScript’s type inference to define it for us. If we were to define it the return type would be `Starters[Name]`. The reason this works is that we have constrained the `Name` generic to extend `keyof Starters`.

## Practical Indices

Index accessed types really shine when deriving types from other types. Imagine we’re building a game that uses some sort of restful service. The backend has done a wonderful job of building a consistent API that describes all entities in the following way.

| **Action** | **HTTP Method** | **Path** |
| --- | --- | --- |
| Get all | ``` GET ``` | ``` /<entity> ``` |
| Get one | ``` GET ``` | ``` /<entity>/:id ``` |
| Create | ``` POST ``` | ``` /<entity> ``` |
| Update | ``` PATCH ``` | ``` /<entity>/:id ``` |
| Delete | ``` DELETE ``` | ``` /<entity>/:id ``` |

Ideally, we’d like a generic factory to create requests for multiple crud-ish entities, like a `HatchedPokemon` or a `Trainer`, to reduce the duplicated logic in our code. One way we could accomplish this is by constraining the type of entity passed into our factory to some base `Entity` type that describes what all entities must have, in our case, this is an `id` value, and then having all the methods returned by the factory use the type of that `Entity`’s id.

```
type Entity = { id: number };
type Updatable<T extends Entity> = Partial<Omit<T, "id">>;

type Requests<T extends Entity> = {
  getOne: (id: number) => Promise<T>;
  getAll: () => Promise<Array<T>>;
  create: (partialEntity: Partial<T>) => Promise<T>;
  update: (id: number, updated: Updatable<T>) => Promise<T>;
  delete: (id: number) => Promise<void>;
};

function factory<T extends Entity>(path: string): Requests<T> {
  // Implementation detail
}
```

This works, but what would happen if, down the long development road, `id` is changed from a `number` to a `string` to conform to the `UUIDv4` standard? We’d have to change it on `Entity` and then on all of our request function types as well. It would be much easier if we just looked up the type of `id` off of the generic passed into the `Request` type.

> **Note:** Notice this is only possible because we have constrained `T` to extend `Entity` in the generic definition

```
type Requests<T extends Entity> = {
  getOne: (id: T["id"]) => Promise<T>;
  getAll: () => Promise<Array<T>>;
  create: (partialEntity: Partial<T>) => Promise<T>;
  update: (id: T["id"], updated: Updatable<T>) => Promise<T>;
  delete: (id: T["id"]) => Promise<void>;
};
```

Using index accessed types we have resolved this issue and any future issue like it down the road.

As we’ve seen, indexed access types are a powerful feature from TypeScript which helps our typing become more flexible and dynamic. Like generics, they will become a staple in our types as we progress through other TypeScript features.

## Exercises

### Exercise 1

Below is an array of Pokemon trainers and a `FavoritePokemon` type currently assigned to any. Using the `pokemonTrainers` array replace the `any` with a type that has the same shape as `favoritePokemon` on the trainers in the array.

 Hint for Exercise 1 (click to reveal) An array is just an object indexed with a number

[Open in CodeSandbox](https://codesandbox.io/s/6syglj?file=/03-index-accessed-types-ex-01.ts)

```
/**
 * Below is an array of Pokemon trainers and a `FavoritePokemon` type currently assigned to any.
 * Using the `pokemonTrainers` array replace the `any` with a type that has the same shape as `favoritePokemon` on the
 * trainers in the array.
 *
 * > Hint:
 * > An array is just an object indexed with a number
 */
export const pokemonTrainers = [
  {
    name: "Ash",
    favoritePokemon: {
      name: "Pikachu",
      pokedexNumber: 25,
      type: ["Electric"],
      attacks: [
        { title: "Quick Attack", type: "Normal", power: 40, accuracy: 100 },
        { title: "Thunder", type: "Electric", power: 110, accuracy: 70 },
        { title: "Volt Switch", type: "Electric", power: 70, accuracy: 100 },
      ],
    },
  },
  {
    name: "Brock",
    favoritePokemon: {
      name: "Onix",
      pokedexNumber: 95,
      type: ["Rock", "Ground"],
      attacks: [
        { title: "Tackle", type: "Normal", power: 40, accuracy: 100 },
        { title: "Iron Tail", type: "Steel", power: 100, accuracy: 75 },
        { title: "Rock Slide", type: "Rock", power: 75, accuracy: 90 },
      ],
    },
  },
];

type FavoritePokemon = any;

```

Click to see the solution

```
import { pokemonTrainers } from "./ex-01";

export type Pokemon = typeof pokemonTrainers[number]["favoritePokemon"];

```

###### On this page...

###### Get help

If you need [help](https://discord.gg/J7ejFsZnJ4) with an exercise, please reach out to us on [Discord](https://discord.gg/J7ejFsZnJ4)

If you find a bug, please [create an issue](https://github.com/bitovi/academy/issues/new) or email [contact@bitovi.com](mailto:contact@bitovi.com?Subject=Training%20Suggestion)

## Join the Bitovi Newsletter

 Do you want to receive updates about new Bitovi Academy courses, Bitovi open source projects, and dev community news? If so, please provide your email. We won’t spam you or give it away for any reason!  
*By providing your email you agree to receive communications from Bitovi*

![](https://bitovi.github.io/academy/static/img/close.svg)

```json
{
     "@context": "http://schema.org",
     "@type": "Organization",
     "mainEntityOfPage":{
          "@type":"WebPage",
          "@id":"https://www.bitovi.com/academy/advanced-typescript/index-accessed-types.html",
          "description": "Learn how to look up types of properties with index accessed types! 
"
     },
     "url": "http://bitovi.com",
     "logo": "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
     "image": "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
     "name": "Bitovi Web App Consulting",
     "alternateName": "Bitovi",
      "naics": "541511",
      "description": "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
     "address": {
          "@type": "PostalAddress",
          "streetAddress": "1134 Pine Tree Lane ",
          "addressLocality": "Libertyville",
          "addressRegion": "IL",
          "addressCountry": "United States",
          "postalCode": "60048"
     },
     "areaServed": {
          "@type": "GeoCircle",
          "geoMidpoint": {
               "@type": "GeoCoordinates",
               "latitude": "41.8781",
               "longitude": "87.6298"
          },
          "geoRadius": "5000 km"
     },
     "telephone": "312-620-0386",
     "email": "contact@bitovi.com",
     "sameAs": [
          "https://www.facebook.com/BitoviLLC/",
          "https://twitter.com/bitovi",
          "https://www.linkedin.com/company/bitovi"
     ]
}
```