Search code examples
typescriptecmascript-6getter

What is the "type" of an ES6 class getter in Typescript?


I have a class that looks like this:

export class WidgetsManager {
  private foo?: boolean;
  private bar?: boolean;
  // ... and so on

  constructor(config: Config | null) {
    this.foo = config.foo;
    this.bar = config.bar;
    // ... and so on
  }

  get hasFoo(): boolean {
    return this.foo === true;
  }

  get hasBar(): boolean {
    return this.bar === true;
  }

 // ... and so on
}

And I create an instance like this:

const mgr = new WidgetsManager({
  foo: true, bar: true,
  // ...and so on, each attribute === true
});

I want to write a unit test and avoid having to write out each and every getter (it's a long list) that I want to test. So I use the following:

Object.getOwnPropertyNames(mgr).forEach(attr => expect(truthyMgr[attr]).toBeTruthy())

The code above give a TS error saying

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'WidgetManager'.
  No index signature with a parameter of type 'string' was found on type 'WidgetManager'.ts(7053)

What is the correct type to use for attr in this situation?


Solution

  • This is actually a quirk of the typing for Object.getOwnPropertyNames.

    Basically the reason why the type of the parameter is Record<string, any> is because you can't maintain any other type invariant. An object can match an interface but have more properties defined on it.

    See this github issue on the typescript repo for more info.