Search code examples
javascripttypescriptindex-signature

No index signature with a parameter of type 'string' was found on type 'typeof Object'


I made a class doing like enum following: https://stackoverflow.com/a/51398471

export default class Juice
{
  [key: string]: any;

  static APPLE = new Juice('APPLE', 'Apple juice');
  static ORANGE = new Juice('ORANGE', 'Orange juice');

  private constructor(private key:string, public readonly text:string) {
  };
}

When I get access with key I defined, it works fine, but it failed when I try to access by dynamically like this:

console.log(Juice.APPLE); //works fine
console.log(Juice['APPLE']); //works fine
const key = 'APPLE'; //works fine
console.log(Juice[key]); //works fine
console.log(Object.keys(Juice).map((key:string) => Juice[key])); // error!

The error is:

TypeScript error in `path`
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'typeof Juice'.
No index signature with a parameter of type 'string' was found on type 'typeof Juice'.  TS7053

Is there someone help me what the cause of the error is and the solution?

Please help, thanks.

I added index signature in the class, but it didn't help

[key: string]: any;
export default class Juice
{
  [key: string]: any;

  static APPLE = new Juice('APPLE', 'Apple juice');
  static ORANGE = new Juice('ORANGE', 'Orange juice');

  private constructor(private key:string, public readonly text:string) {
  };
}

Get the list of the enum class.


Solution

  • The issue appears to be using Object.keys as it will always iterate through a list of string vs a list of strings that are keys to the object. If you want to get all the values of an object I would instead use Object.values. However this will cause an issue as the constructor will also be returned as a value (prototype) which will cause other typing issues.

    I would recommend having your static juices as a seperate object you can reference when needed. Example:

    class Juice {
      constructor(private key: string, public readonly text: string) {}
    }
    
    const juices = {
      APPLE: new Juice('APPLE', 'Apple juice'),
      ORANGE: new Juice('ORANGE', 'Orange juice')
    };
    export default juices;
    
    console.log(Object.values(Juice));
    
    const test: keyof typeof juices = 'APPLE';
    console.log(juices[test]);
    

    I hope this was helpful.