Last updated: Feb 28, 2024
Reading time·3 min
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.
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; };
And here is an example of how the error occurs when using a 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: 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.
To solve the error, use mapped types.
enum EmailStatus { Read = 'READ', Unread = 'UNREAD', Draft = 'DRAFT', } // 👇️ make sure you use type here (not interface) type Status = { [key in EmailStatus]: string; };
And here is an example of using mapped types with a 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 will get an error.
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
.
Record
utility type to solve the errorA different approach to solving the error is to use the Record
utility type.
// 👇️ Using Enums enum EmailStatus { Read = 'READ', Unread = 'UNREAD', Draft = 'DRAFT', } type Status = Record<EmailStatus, string>
And here is an example of using the Record
utility type with a union type.
// 👇️ 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.
You can learn more about the related topics by checking out the following tutorials: