close

Filter

loading table of contents...

Studio Developer Manual / Version 2301

Table Of Contents
Declaring the Config Type in TypeScript

In TypeScript, each class using the Ext Config system needs an additional interface that describes its Config options. The design goal for the representation of this Config interface is to only declare and document Config properties once, although they usually re-appear on the class itself. Also, we need to distinguish simple Configs and advanced ("bindable") Configs. Last but not least, Config objects usually only specify a subset of all possible properties.

Here, the TypeScript utility types Pick and Partial come in handy. Pick allows to pick a list of specified member declarations from another type. Partial creates a new type that is exactly like the source type, only that all members are optional, as if they were declared with the ? modifier.

All Config properties are declared in the class itself. "Simple" Config properties are just properties with an optional default value, while bindable Config properties must be specified as an accessor pair, typically encapsulating a private field. The additional Config type is then declared as an interface using the partial type of picking those Config properties from the class. By convention, we name this interface like the class, suffixed with Config.

import Component from "@jangaroo/ext-ts/Component";

interface MyClassConfig extends Partial<Pick<MyClass,
  "configOption1" |
  "configOption2">> {
}

class MyClass extends Component {
  /**
   * Simple Config property.
   */
  configOption1: string = "foo";

  #configOption2: number[] = [42];
  /**
   * Bindable Config property.
   */
  get configOption2(): number[] {
    return this.#configOption2;
  }
  set configOption2(value: number[]) {
    this.#configOption2 = value;
  }

  constructor(config: MyClassConfig) {
    super(config);
  }
}

export default MyClass;

Example 5.8.  Simple and Bindable Config Properties in TypeScript


To also export the additional interface, the most straightforward option seemed to be using a named export. But this has disadvantages:

  • When a class declares no additional Config properties, but just reuses the Config type of its superclass, it would have to re-export the super Config type.

  • When using both the class and its Config type, you need two import identifiers, which is especially cumbersome when there is a name clash, because you need to rename both.

So we decided to assign the Config type to the class, which can be done in TypeScript by declaring a "virtual" class member, and use the name Config for it.

interface MyClassConfig ...

class MyClass ... {
  declare Config: MyClassConfig;
  ...
}

Example 5.9.  Declaring Config type as virtual class member


This allows to access the Config type by importing the class and then use the utility type called Config (imported from @jangaroo/runtime/Config). As this pattern is followed by all classes using the Ext Config System, also the Ext TS declarations of all framework components, we can complement the example by extending the superclass Config type. The pattern should also be used to refer to the Config type for the constructor parameter.

import Config from "@jangaroo/runtime/Config";
import Component from "@jangaroo/ext-ts/Component";

interface MyClassConfig extends Config<Component>, Partial<Pick<MyClass,
  "configOption1" |
  "configOption2">> {
}

class MyClass extends Component {
  declare Config: MyClassConfig;

  //...

  constructor(config: Config<MyClass>) {
    super(config);
  }
}

export default MyClass;

Example 5.10.  Extending superclass Config type


Search Results

Table Of Contents
warning

Your Internet Explorer is no longer supported.

Please use Mozilla Firefox, Google Chrome, or Microsoft Edge.