Beginner's TypeScript #24
Published: 2024-01-16 15:00:00

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tjg1yyrcg3iy63zm19a4.png)

⭐ **Error Message: "Expression Can't Be Used To Index Type X"** ⭐

We have an object named **productPrices**. It has three properties: **Apple**, **Banana**, and **Orange**, each with a price value:

```ts
const productPrices = {
	Apple: 1.2,
	Banana: 0.5,
	Orange: 0.8,
}
```

We also have a function **getPrice** that takes in a **productName** as a parameter:

```ts
const getPrice = (productName: string) => {
	return productPrices[productName]; // red squiggly line under productPrices[productName]
}
```

The **getPrice** function is designed to index into the **productPrices** object using the **productName** provided.

There is an error under **productPrices** when trying to index into the object:

```ts
// hovering over productPrices[productName] shows:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ Apple: number; Banana: number; Orange: number; }'.
```

We will figure out why this error is occurring.

👉 **Solution**

We have an error because we are attempting to index into the **productPrices** object with a string.

Let's break the error down.

The **"implicit 'any'"** part of the error message is TypeScript telling us it does not know what type the type is supposed to be.

For the **"index"** part of the error message, we need to remember that indexing means accessing an object using dot notation or dynamic string notation.

When typing **productPrices** followed by a **.** or **[]**, TypeScript suggests autocompletion for one of the three possible keys: **Apple**, **Banana**, or **Orange**.

The three possible values are like an index signature for how the object can be called.

There are a few ways we can update **productPrices** to resolve this error:

1️⃣ **Use a Record**

One option is to update **productPrices** to use a **Record** type where the index is a **string**, followed by a **number**:

```ts
const productPrices: Record<string, number> = {
	Apple: 1.2,
	Banana: 0.5,
	Orange: 0.8,
}
```

With this **Record** setup, we could pass in any string to index into the object whether it exists in **productPrices** or not.

2️⃣ **Error in the Function**

Another option is to update the **getPrice** function to use a **union** type for the **productName** parameter to ensure the function only accepts specific product names:

```ts
const getPrice = (productName: "Apple" | "Banana" | "Orange") => {
	return productPrices[productName];
}

getPrice("Pear"); // red squiggly line under "Pear"
```

With this change, calling **getPrice** with an invalid product name will result in a TypeScript error.

3️⃣ **Using keyof typeof**

A third option is to use **keyof typeof** to get the type of the **productPrices** object and use that as the type for the **productName** parameter:

```ts
const getPrice = (productName: keyof typeof productPrices) => {
	return productPrices[productName];
}
```

Using **keyof typeof** is a good option because it ensures that the **productName** parameter is always a valid key for the **productPrices** object.

When hovering over the call to getPrice, we can see that it expects a value of type **"Apple" | "Banana" | "Orange"**:

```ts
getPrice("Pear") // red squiggly line under "Pear"

// hovering over getPrice shows:
getPrice: (productName: "Apple" | "Banana" | "Orange") => number;
```

4️⃣ **Casting**

With casting we can cheat the type system and bypass the TypeScript error.

Assuming we know the **productName** will definitely be one of **Apple**, **Banana**, or **Orange**, we can use casting to bypass the TypeScript error.

To do this, we will use **keyof typeof** inside the actual indexing:

```ts
const getPrice = (productName: string) => {
	return productPrices[productName as keyof typeof productPrices]
}
```

The best thing you should do in this situation is to provide proper types to your variables and functions. 🚀

---

I hope you found it useful. Thanks for reading. 🙏

Let's get connected! You can find me on:
- **Medium:** https://medium.com/@nhannguyendevjs/
- **Dev**: https://dev.to/nhannguyendevjs/
- **Hashnode**: [https://nhannguyen.hashnode.dev](https://nhannguyen.hashnode.dev/)/
- **Linkedin:** https://www.linkedin.com/in/nhannguyendevjs/
- **X (formerly Twitter)**: https://twitter.com/nhannguyendevjs/
- **Buy Me a Coffee:** [https://www.buymeacoffee.com/nhannguyendevjs/](https://www.buymeacoffee.com/nhannguyendevjs/)