h-Reser
h-Reser

Reputation: 177

Typescript: index signature on class properties

I am getting an error about index signatures when trying to dynamically access my static and instantiated class properties. I've found a lot of people talking about this error online, but I've not yet been able to fix the issue.

I was able to reproduce the issue on a simple class:

interface MyClassInterface {
  name: string;
  getInstanceProperty( propertyName: string ): string;
  getStaticProperty( propertyName: string ): number;
}

class MyClass implements MyClassInterface {

  public name: string;

  private static age: number;

  public constructor( theName: string, theAge: number ) {

    this.name = theName;
    MyClass.age = theAge;

  }

  public getInstanceProperty( propertyName: string ): string {

    return this[propertyName];
    // Typescript error:
    // Element implicitly has an 'any' type because type 'MyClass' has no index signature.

  }

  public getStaticProperty( propertyName: string ): number {

    return MyClass[propertyName];
    // Typescript error:
    // Element implicitly has an 'any' type because type 'typeof MyClass' has no index signature.

  }

}

const myClass = new MyClass( "John", 35 );

console.log(
  myClass.getInstanceProperty( "name" ),
  myClass.getStaticProperty( "age" )
); // Outputs "John 35" in the console

I found that it is possible to avoid the error in getInstanceProperty() by adding a type information inside of the class as follows:

class MyClass implements MyClassInterface {
  [key: string]: any;

  // ...
}

Is it possible to add this in the class interface? I haven't managed to do it yet. I suppose that I need a similar modification somewhere for the static properties, but I don't know how to do it. Any idea?

I have reproduced this code in the TypeScript Playground. You just need to enable the noImplicitAny option to show the errors.

Many thanks!

Upvotes: 5

Views: 4697

Answers (2)

nbl7
nbl7

Reputation: 551

Another solution can be:

class MyClass {

    public static myMethod(variable:any):string{

    }

}

interface Indexable {
    [key:string]:any;
}

export const MyExportedClass = MyClass as Indexable;

Upvotes: 1

Daniel W Strimpel
Daniel W Strimpel

Reputation: 8470

There has been an open issue on TypeScript's GitHub for a few years around this. It doesn't seem to be possible to have a static index signature currently.

I think the only way around this limitation is to help the compiler out by letting it know that your class has a static index signature by using a type assertion like below.

interface Indexable {
  [key: string]: any;
}

class MyClass {
    ...
    public getStaticProperty( propertyName: string ): number {
      return (MyClass as Indexable)[propertyName];
    }
    ...
}

Upvotes: 4

Related Questions