Reputation: 759
I am attempting to use Javarome's answer to a previous TypeScript question regarding how to use an object in an enum:
class Material {
public static readonly ACRYLIC = new Material(`ACRYLIC`, `AC`, `Acrylic`);
public static readonly ALUM = new Material(`ALUM`, `AL`, `Aluminum`);
public static readonly CORK = new Material(`CORK`, `CO`, `Cork`);
public static readonly FOAM = new Material(`FOAM`, `FO`, `Foam`);
// private to diallow creating other instances of this type.
private constructor(
public readonly key: string,
public readonly id: string,
public readonly name: string
) {}
public toString(): string {
return this.key;
}
}
Unfortunately, I am running into an issue later in the code when I attempt to use bracket-syntax (because it's in a for-of
loop):
const materials: string[] = [`ACRYLIC`, `FOAM`];
for (const materialKey of materialsArray) {
const material: Material = Material[materialKey];
// ...
}
That pops up a huge TS error [TS(7053)] with the following message:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof Material'.
No index signature with a parameter of type 'string' was found on type 'typeof Material'.ts(7053)
I have been Googling for hours but have found nothing that helps. Is there any way to reference this "enum" using bracket-syntax?
Upvotes: 3
Views: 5618
Reputation: 20152
The issue with this code is exactly:
const materials: string[] = [`ACRYLIC`, `FOAM`];
There is no relation between possible properties of Material
static class and a list of strings. The key to the problem is to specify in type that the list which we have is a list of only allowed properties which have values as Material
type.
It can be achieved by Exclude type utility. Take a look at below example:
type MaterialKeys = Exclude<keyof typeof Material, 'prototype'>;
const materialsArray: MaterialKeys[] = [`ACRYLIC`, `FOAM`];
for (const materialKey of materialsArray) {
const material: Material = Material[materialKey];
// ...
}
For more informations: Exclude<keyof typeof Material, 'prototype'>;
will take all keys of Material
type and exclude from it the prototype
, so we will in result have all static fields, and that is what we want though.
Upvotes: 2