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

avatar
Borislav Hadzhiev

Last updated: Feb 28, 2024
3 min

banner

# 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.

Here is an example of how the error occurs when using enums.

index.ts
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; };

an index signature parameter type cannot be literal type or generic type

And here is an example of how the error occurs when using a union type.

index.ts
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: EmailStatuses]: 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.

# Use mapped types to solve the error

To solve the error, use mapped types.

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

use mapped types to solve the error

The code for this article is available on GitHub

And here is an example of using mapped types with a union type.

index.ts
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 will get an error.

index.ts
interface Status { // ⛔️ Error [key in EmailStatus]: string; };

We used mapped types to take all of the properties of the enum and union and changed their values to be of type string.

# Use the Record utility type to solve the error

A different approach to solving the 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>

use record utility type to solve the error

The code for this article is available on GitHub

And here is an example of using the Record utility type with a union type.

index.ts
// 👇️ Using Union type type EmailStatuses = 'Read' | 'Unread' | 'Draft'; type StatusFromUnion = Record<EmailStatuses, string>

The code sample 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.

If you'd like to read more about literal types in TypeScript, click on the link and follow the instructions.

# 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.