What does {[key: string]: string} mean in TypeScript

avatar

Borislav Hadzhiev

Last updated: Feb 18, 2022

banner

Photo from Unsplash

The {[key: string]: string} type in TypeScript #

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

index.ts
// 👇️ function returning index signature // (a key-value structure with key and value strings) function getObj(): { [key: string]: string } { return { name: 'Tom', country: 'Chile' }; } // 👇️ Interface using index signature interface Person { [index: string]: string; } // 👇️ const p1: Person const p1: Person = { name: 'Tom', country: 'Chile' }; // 👇️ Type using index signature type Animal = { [index: string]: string; }; const a1: Animal = { name: 'Alfred', type: 'dog' };

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

The index signature in the examples means that when an the object is indexed with a string, it will return a string.

You might also see the index signature {[key: string]: any} in examples. It represents a key-value structure that when indexed with a string returns a value of any type (very broad).

Let's look at an example of how TypeScript warns us if we try to add a value of a different type than specified in our index signature.

index.ts
interface Person { [index: string]: string; } // ⛔️ ERROR: Type 'number' is not assignable to type 'string'. const p1: Person = { name: 'Tom', age: 30 };

We've specified that when the object that has a type of Person is indexed with a string, it should return a string.

Trying to set a key that is a string with a value of number gets us an error.

You might try to override the type of a specific property with an index signature.

index.ts
interface Person { [index: string]: string; // ⛔️ Error: Property 'age' of type 'number' is not // assignable to 'string' index type 'string'. age: number; }

But the type of the age property in the example does not match the type of the string index, so TypeScript gives us an error.

In this situation, you can set the type of the string index to a union.

index.ts
interface Person { [index: string]: string | number; age: number; name: string; } // 👇️ const p1: Person const p1: Person = { name: 'Tom', country: 'Chile', age: 30 };

The type of the values with an index signature of type string is a union of string and number.

The age and name properties have a value that is a subtype of the union, so we don't get an error.

Trying to add a property to the type that is not in the union, would cause an error.

index.ts
interface Person { [index: string]: string | number; age: number; name: string; // ⛔️ ERROR: Property 'colors' of type 'string[]' is not assignable // to 'string' index type 'string | number'.ts(2411) colors: string[]; }

You can also set an index signature to readonly if you need to prevent assignment to their indices.

index.ts
interface ReadonlyObj { readonly [index: string]: string; } const obj: ReadonlyObj = { name: 'Tom', country: 'Chile', }; // ⛔️ Index signature in type 'ReadonlyObj' // only permits reading. obj.name = 'Alfred';

We set the string index's type to readonly, so the type checker gives us an error if we try to write to a property that has a string key.

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.