1

I can't seem to figure out how to type the index signature properly here. I have an enum and need to iterate through it to put some JSX on the screen. I can guess what it's telling me but I can't solve it in my code. Both the Category[el] statements are the problem.

export enum Category {
    All = 'ALL',
    Employee = 'EMPLOYEE',
    Gear = 'GEAR',
    Room = 'ROOM',
    Other = 'OTHER',
}

My simplified function to render some JSX is:

    const renderCategories = (): ReactElement | ReactElement[] => {
        return Object.keys(Category).map(el => {
            return (
                <Option key={el} value={Category[el]}>
                    <span>{` (${someOtherData.filter((e) => e.type === Category[el].length})`}</span>
                </Option>
            );
        });
    };

TS tells me:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof Category'.
  No index signature with a parameter of type 'string' was found on type 'typeof Category'.
Florian Kuc
  • 127
  • 7

2 Answers2

2

This use case is quite common as using Object.keys which always infer each key as string which is incompatible with key of like enum or an object with a specific type.

But Typescript still allows us to cast this each key to a type which means we just simply cast back to type of above enum.

Here is the snippet reflecting the above explanation:

export enum Category {
  All = 'ALL',
  Employee = 'EMPLOYEE',
  Gear = 'GEAR',
  Room = 'ROOM',
  Other = 'OTHER',
}

// A common type to detect the enum type

type EnumType = typeof Category;
type EnumKeyType = keyof EnumType;

// Then cast back to our desired type

someOtherData.filter((e) => e.type === Category[el as EnumKeyType].length) // cast `el as EnumKeyType`

tmhao2005
  • 14,776
  • 2
  • 37
  • 44
0

You can add the following index signature to the enum:

export enum Category {
    All = 'ALL',
    Employee = 'EMPLOYEE',
    Gear = 'GEAR',
    Room = 'ROOM',
    Other = 'OTHER',
    [key: string]: string,
}
Alex K
  • 832
  • 4
  • 8
  • Unfortunately, I can't since I'm getting the following errors on that last line then: Enum member must have initializer.ts(1061) Computed property names are not allowed in enums.ts(1164) Duplicate identifier 'string'.ts(2300) – Florian Kuc Dec 21 '20 at 15:57
  • Ahh, I see, this might actually be a duplicate of this: https://stackoverflow.com/questions/47896885/iterate-on-string-enum – Alex K Dec 21 '20 at 16:06
  • This does not work in Angular 14+ as enums are not recognized as having index signatures – ma11achy May 09 '23 at 15:20