3

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?

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

You, sir, are a genius. Thank you so much for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.