close

Filter

loading table of contents...

CoreMedia Content Cloud v11 Upgrade Guide / Version 2110

Table Of Contents
7.3.1.5.2 Mixins in TypeScript

In TypeScript, we use a quite similar approach like in ActionScript, but fortunately, the syntax is much more elegant.

To understand how mixins work, it helps to know that in TypeScript, a class consists of a it's run-time JavaScript value and a type, which is only relevant for type checking / at compile-time. The class identifier represents both aspects. Depending on context, it is clear whether the value, the type, or both are meant. When a class A extends another class B, in the extends clause, B refers to both the value (JavaScript class A will at run-time extend JavaScript class B) and the type (TypeScript type A will at compile-time be a sub-type of type B). When using a class identifier behind a colon or in the implements clause of a class, only its type aspect it used. This allows to use a class in an implements clause! This equals implementing the interface extracted from that class.

Another TypeScript concept that is relevant here and closely related is declaration merging. In TypeScript, a type with the same identifier can be declared multiple times, and all declarations are merged. Since a class declares a value and a type, and an interface only declares a type, you cannot declare the same class twice, but you can declare a class and an interface using the same identifier. What happens is that the interface extracted from the class is merged with the additionally declared interface. In this case, TypeScript does not complain about the class not implementing the additional interface methods. We call such an interface a companion interface of the class, as it comes together with the class and adds more declarations (the ones we had to declare as native in ActionScript).

Using these ingredients, we can declare mixins in TypeScript as follows.

As in Ext JS, a mixin is a usual TypeScript class. A mixin client class implements the interface automatically extracted from the mixin class, in other words, it directly implements the mixin class!

But that does not suffice: We have to specify that we do not only want to use the interface, but also want to mix in the mixin's methods at run-time. We learned about the mixin() utility function in the interface chapter. Maybe now it becomes clear why it is called like that: it can do more than just mix in the identity of an interface: it actually mixes in any class with all its members into the client class!

Last thing to do is again to prevent the type checker from complaining about missing implementations of the mixin interface, since it does not know about the mixin magic. This is much more elegant in TypeScript than in ActionScript: Instead of re-declaring every single member using the native keyword, we just declare a companion interface of the mixin client class and let that extend the mixin class interface. We could even leave out the implements clause of the mixin client class itself, but to emphasize what's going on (and to help some IDEs that don't really support declaration merging completely), during conversion, we generate both clauses.

All in all, the above example results in the following quite more compact TypeScript code.

// ./acme/MyMixin.ts
class MyMixin {
  #mixinConfig: string = "";

  get mixinConfig(): string {
    return this.#mixinConfig;
  }

  set mixinConfig(value: string) {
    this.#mixinConfig = value;
  }

  doSomething(): number {
    return this.#mixinConfig.length;
  }
}

export default MyMixin;


// ./MixinClient.ts
import { mixin } from "@jangaroo/runtime";
import Component from "@jangaroo/ext-ts/Component";
import MyMixin from "./acme/MyMixin";

class MixinClient extends Component implements MyMixin {
  constructor(config: any = null) {
    super(config);
    this.doSomething();
  }
}

// companion interface, so we don't need to re-declare all mixin members:
interface MixinClient extends MyMixin {}

// use Jangaroo utility method to perform mixin operation:
mixin(MixinClient, MyMixin);

export default MixinClient;

Example 7.4. Mixins in TypeScript example


Search Results

Table Of Contents
warning

Your Internet Explorer is no longer supported.

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