Element implicitly has an 'any' type because expression of type 'string' can't be used to index type

avatar
Borislav Hadzhiev

Last updated: Jan 22, 2023
6 min

banner

# Table of Contents

  1. Element implicitly has an 'any' type because expression of type 'string' can't be used to index type
  2. Element implicitly has 'any' type because index expression is not of type 'number'
If you got the error when accessing an array at an index, click on the second subheading.

# Element implicitly has an 'any' type because expression of type 'string' can't be used to index type

The error "Element implicitly has an 'any' type because expression of type 'string' can't be used to index type" occurs when we use a string to index an object with specific keys.

To solve the error, type the string as one of the object's keys.

Here is an example of how the error occurs.

index.ts
const str = 'name' as string; const obj = { name: 'Bobby Hadz', country: 'Chile', }; // โ›”๏ธ Error: Element implicitly has an 'any' type // because expression of type 'string' can't be used // to index type '{ name: string; }'. // No index signature with a parameter of type 'string' // was found on type '{ name: string; }'.ts(7053) obj[str];

element implicitly has an any type because expression

The str variable has a type of string and this could be any string.

We got the error when we tried to access an object that has a name and country properties.

TypeScript is telling us that the string type is too broad and not all strings are keys in the object, so we have to make sure the specific string is one of the object's keys.

# Solve the error using a type assertion

The first way to solve the error is to use a type assertion.

index.ts
const str = 'name' as string; const obj = { name: 'Bobby Hadz', country: 'Chile', }; // ๐Ÿ‘‡๏ธ "Bobby Hadz" console.log(obj[str as keyof typeof obj]); // ๐Ÿ‘‡๏ธ type T = "name" | "country" type T = keyof typeof obj;

solve the error using type assertion

We used a type assertion to indicate to TypeScript that the str variable is a union type containing only the keys of the object.

Now TypeScript lets us access the specific property without throwing the error.

We used keyof typeof to get a union type of the object's keys.

If you are working with a type directly, you would just use keyof MyType to get a union of the object's keys.

index.ts
const str = 'name' as string; interface Person { name: string; country: string; } const obj: Person = { name: 'Bobby Hadz', country: 'Chile', }; console.log(obj[str as keyof Person]); // ๐Ÿ‘‰๏ธ "Bobby Hadz" // ๐Ÿ‘‡๏ธ type T = "name" | "country" type T = keyof Person;

using keyof mytype

Notice that we used keyof Person and not keyof typeof Person because Person is a type and not an object.

# Typing the variable to solve the error

An even better way to solve this issue is to type the str variable as keyof Person to indicate to TypeScript that the string will only ever be one of the object's keys.

index.ts
interface Person { name: string; country: string; } // ๐Ÿ‘‡๏ธ this will only ever be one of object's keys const str: keyof Person = 'name'; const obj: Person = { name: 'Bobby Hadz', country: 'Chile', }; console.log(obj[str]); // ๐Ÿ‘‰๏ธ "Bobby Hadz"

typing variable to solve the error

Now we don't have to use type assertions in our code.

Type assertions are used when we have information about the type of a value that TypeScript can't know about.

When using them, we effectively tell TypeScript that value X will be of type X and not to worry about it. This could cause runtime errors if we are wrong.

Here is another example of how you could type a value to only be one of the object's keys.

index.ts
interface Person { name: string; country: string; } const obj1: Person = { name: 'Bobby Hadz', country: 'Chile', }; interface AccessPerson { keyName: keyof Person; // ๐Ÿ‘ˆ๏ธ only one of Person's keys } const obj2: AccessPerson = { keyName: 'country', }; console.log(obj1[obj2.keyName]); // ๐Ÿ‘‰๏ธ "Chile"

type variable to be one of object keys

We are using the obj2.keyName property to access a property in obj1.

To be able to do this, we had to type the keyName property in obj2 to be of type keyof Person.

The keyName property in obj2 can only ever have a value of name or country, so TypeScript allows us to safely access the properties in obj1.

This is necessary because not all string values in the world are keys in the specific object. For TypeScript to let us access the object's properties, we have to convince it that the string is one of the object's keys.

This is the most type-safe solution to the error because if we ever try to change the value of obj2.keyName to an incompatible type, we'd get an error.

index.ts
interface Person { name: string; country: string; } interface AccessPerson { keyName: keyof Person; } const obj2: AccessPerson = { keyName: 'country', }; // โ›”๏ธ Error: Type '"hello"' is not // assignable to type 'keyof Person'.ts(2322) obj2.keyName = 'hello';

Trying to set obj2.keyName to any other value than name or country causes an error.

You might also get the Parameter 'X' implicitly has an 'any' type when a function's parameter has an implicit type of any.

# Element implicitly has 'any' type because index expression is not of type 'number'

The error "Element implicitly has 'any' type because index expression is not of type 'number'" occurs when an array is indexed with a value that is not a number.

To solve the error, use an object if storing key-value pairs or use a type assertion.

element implicitly has any type index expression not number

Here are 2 examples of how the error occurs.

index.ts
const arr = ['a', 'b', 'c']; // โ›”๏ธ Error: Element implicitly has an 'any' type // because index expression is not of type 'number'.ts(7015) const result = arr['a']; // -------------------------------------------------- const obj: { [key: number]: string } = { 0: 'a', 1: 'b', }; // โ›”๏ธ Error: Element implicitly has an 'any' type because // index expression is not of type 'number'.ts(7015) const result2 = obj['a'];

In the first example, we try to use a string to access an array element at index.

In the second example, we have an object with numeric keys and try to use a string key to index it.

# Accessing an array at an index

If you are trying to access an array element at an index, use a zero-based number.

index.ts
const arr = ['a', 'b', 'c']; const result = arr[0]; console.log(result); // ๐Ÿ‘‰๏ธ "a"

If the type of the value you're using to index the array or object is incorrect, use a type assertion.

index.ts
const arr = ['a', 'b', 'c']; const result = arr['1' as unknown as number]; console.log(result); // ๐Ÿ‘‰๏ธ "b"

Type assertions are used when we have information about the type of a value that TypeScript can't know about.

We effectively tell TypeScript that the value is of type number and not to worry about it.

# Suppressing the errors for your entire project

If you want to suppress the implicit any index errors for your entire project, you can do that in your tsconfig.json file.

tsconfig.json
{ "compilerOptions": { "suppressImplicitAnyIndexErrors": true, // ... rest } }

When the suppressImplicitAnyIndexErrors option is set to true, no implicit any errors are reported when indexing into objects or arrays.

# Use an object with an index signature to store key-value pairs

If you are trying to store key-value pairs, use an object with an index signature and string keys.

index.ts
type Person = { [key: string]: any; }; const obj: Person = { name: 'Bobby Hadz', }; obj.age = 30; obj.salary = 100; obj.tasks = ['develop', 'test']; console.log(obj['age']); // ๐Ÿ‘‰๏ธ 30 console.log(obj['salary']); // ๐Ÿ‘‰๏ธ 100

use object with index signature to store key value pairs

The {[key: string]: any} syntax is an index signature in TypeScript and is used when we don't know all the names of a type's properties and the shape of the values ahead of time.

The index signature in the example means that when the object is indexed with a string, it will return a value of any type.

You can also explicitly add property names and types you know about in advance.

index.ts
type Person = { [key: string]: any; name: string; // ๐Ÿ‘ˆ๏ธ add name property of type string country: string; // ๐Ÿ‘ˆ๏ธ add country property of type string }; const obj: Person = { name: 'Bobby Hadz', country: 'Germany', }; obj.age = 30; obj.salary = 100; obj.tasks = ['develop', 'test']; console.log(obj['age']); // ๐Ÿ‘‰๏ธ 30 console.log(obj['salary']); // ๐Ÿ‘‰๏ธ 100

explicitly add property names you know in advance

We explicitly typed the name and country properties. This provides better type safety and IDE autocompletion for the specified properties.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev