An index signature parameter type cannot be a literal type or a generic type

avatar

Borislav Hadzhiev

Last updated: Mar 13, 2022

banner

Photo from Unsplash

An index signature parameter type cannot be a literal type or a generic type #

The error "An index signature parameter type cannot be a literal type or a generic type" occurs when we use an incompatible type for an index signature parameter, e.g. union or enum. To solve the error use a mapped object type, e.g. type MyType = {[key in MyUnion]: string;}.

Here are 2 examples of how the error occurs.

index.ts
// 👇️ Using ENUMS 👇️ enum EmailStatus { Read = 'READ', Unread = 'UNREAD', Draft = 'DRAFT', } type Status = { // ⛔️ Error: An index signature parameter type // cannot be a literal type or generic type. // Consider using a mapped object type instead.ts(1337) [key: EmailStatus]: string; }; // 👇️ Using UNION type 👇️ type EmailStatuses = 'Read' | 'Unread' | 'Draft'; type StatusFromUnion = { // ⛔️ Error: An index signature parameter type // cannot be a literal type or generic type. // Consider using a mapped object type instead.ts(1337) [key: EmailStatus]: string; };

We are using an index signature in the Status and StatusFromUnion types, but the type of the key is not one of the allowed types, which are string, number, symbol or template literal type.

To solve the error, use mapped types.

index.ts
// 👇️ Using Enums enum EmailStatus { Read = 'READ', Unread = 'UNREAD', Draft = 'DRAFT', } // 👇️ make sure you use type here (not interface) type Status = { [key in EmailStatus]: string; }; // 👇️ Using Union type type EmailStatuses = 'Read' | 'Unread' | 'Draft'; // 👇️ make sure you use type here (not interface) type StatusFromUnion = { [key in EmailStatuses]: string; };

Notice that we are using the in keyword in our index signature. This is used to refer to the specific properties in the enum and union.

Make sure you are using a type alias and not an interface when using mapped types.

If you use a mapped type in an interface instead of a type alias, you would get the error: "A mapped type may not declare properties or methods".

index.ts
interface Status { // ⛔️ Error: A mapped type may not declare // properties or methods.ts(7061) [key in EmailStatus]: string; };

In the example, we use mapped types to take all of the properties of the enum and union and change their values to be of type string.

A different approach to solving the "An index signature parameter type cannot be a literal type or a generic type" error is to use the Record utility type.

index.ts
// 👇️ Using Enums enum EmailStatus { Read = 'READ', Unread = 'UNREAD', Draft = 'DRAFT', } type Status = Record<EmailStatus, string> // 👇️ Using Union type type EmailStatuses = 'Read' | 'Unread' | 'Draft'; type StatusFromUnion = Record<EmailStatus, string>

This code snippet achieves the same result as the one that used mapped types.

The Record utility type constructs an object type based on the provided types for the keys and values.

Conclusion #

The error "An index signature parameter type cannot be a literal type or a generic type" occurs when we use an incompatible type for an index signature parameter, e.g. union or enum. To solve the error use a mapped object type, e.g. type MyType = {[key in MyUnion]: string;}.

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.