Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: index signature on class properties

Tags:

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!

like image 748
h-Reser Avatar asked Nov 07 '18 15:11

h-Reser


People also ask

How do I create a index signature in TypeScript?

The index signature consists of the index name and its type in square brackets, followed by a colon and the value type: { [indexName: KeyType]: ValueType } . KeyType can be a string , number , or symbol , while ValueType can be any type.

Why do we need Index signature TypeScript?

Index signature is used to represent the type of object/dictionary when the values of the object are of consistent types. Assume that we have a theme object which allows us to configure the color properties that can be used across the application. The values will be consistent with the type string.

What is a signature in TypeScript?

In TypeScript we can express its type as: ( a : number , b : number ) => number. This is TypeScript's syntax for a function's type, or call signature (also called a type signature). You'll notice it looks remarkably similar to an arrow function—this is intentional!

Is incompatible with index signature?

The error "Property is incompatible with index signature" occurs when a property is not compatible with the specified type of the index signature. To solve the error, change the type of the property or use a union to update the type in the index signature.


2 Answers

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];
    }
    ...
}
like image 115
Daniel W Strimpel Avatar answered Nov 15 '22 06:11

Daniel W Strimpel


Another solution can be:

class MyClass {

    public static myMethod(variable:any):string{

    }

}

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

export const MyExportedClass = MyClass as Indexable;

like image 45
nbl7 Avatar answered Nov 15 '22 06:11

nbl7