Studio Developer Manual / Version 2406.0
Table Of Contents
Now, we have strictly typed Config objects, but they lack xclass
/alias
/xtype
properties, which Ext uses to determine the target class when instantiating a Config
object later (see Section, “Advanced Ext JS Config System”).
Since we do not want to specify the Config type twice, once as a TypeScript type and once as a utility
function that add the target class indicator, we combine both into one.
To this end, the generic Config
function supports an overloaded signature which takes as
first argument the target class which must define a Config type and as second (optional) argument a Config
object of the corresponding Config type, and returns that Config object complemented by
xclass
/alias
/xtype
properties taken from the class.
With this new usage of the Config
function, you can now create Ext Config objects like so:
import Config from "@jangaroo/runtime/Config"; import MyClass from "./MyClass"; ... // use Config function with target class + config object: const myClassConfig: Config<MyClass> = Config(MyClass, { // inherited from Config<Component>: id: "4711", // MyClass Config property: configOption1: "bar", // an undeclared property now *does* lead to a type error: untyped: new Date(), // type error: '"42" is not assignable to type number[]': configOption2: "42", }); ...
Example 5.13. Create Ext Config objects with Config function
As you can see, the syntax is very similar to using Config
for a strict type-check.
The crucial difference is that MyClass
is not a type parameter (which is just a compiler hint
and only relevant for type checking), but an argument of the function call. The class reference is needed
at runtime to determine the xclass
etc. and add it to the config object.
Although this Config
signature still has a type parameter, is should never be necessary to
specify it explicitly, just leave it to TypeScript's type inference.
If you use a class as first argument, but leave out the second one, the Config
function
returns an empty Config object with just the target class marker (xclass
, xtype
,
...). This comes in handy for simple components like Config(Separator)
.
TypeScript automatically distinguishes the two one-argument usages of Config
by overloaded
signatures, one with a Config object, the other with a class that declares a Config type.
In the rare case that you need to instantiate the "real" object from a given Config object, you have different options:
import { cast } from "@jangaroo/runtime"; import Ext from "@jangaroo/ext-ts"; // Alternatives // ============ // using constructor directly // xclass of Config object is ignored: const myClassInstance: MyClass = new MyClass(myClassConfig); // using Ext.create() with class and Config object // xclass of Config object is ignored: const myClassInstance: MyClass = Ext.create(MyClass, myClassConfig); // using Ext.create() with Config object only, type on left-hand side // must repeat target class, but incompatible class and Config type would be reported: const myClassInstance: MyClass = Ext.create(myClassConfig); // using Ext.create() with type parameter and Config object // must repeat target class, but incompatible class and Config type would be reported: const myClassInstance = Ext.create<MyClass>(myClassConfig));
Example 5.14. Instantiate object from Config object
The first two usages are when you know which target class to create, anyway, so you would construct
myClassConfig
without any xclass
, but just use the strict Config type function.
The latter two usages are when the Config object might have its own xclass
of some
MyClass
subclass. Ext.create()
uses the xclass
to instantiate the
corresponding class, and the resulting object is type-compatible with MyClass
.
This is the kind of mechanism used by Ext.Container
to instantiate its items
.
But the best thing is, that if you want to create an instance directly, you can do so in a strongly typed
fashion with full IDE support using an inline, ad-hoc Config object, which does not need any
Config
usage:
const myClassInstance: MyClass = new MyClass({ id: "4711", configOption1: "bar", configOption2: [42, 24] });
Example 5.15. Inline ad-hoc Config object
In other words, the difference between creating a Config object and creating an instance is just using
Config(MyClass, ...)
versus using new MyClass(...)
.
Note that when creating the component tree, you usually use Config objects, while certain elements like
Action
s require instantiation. Any Ext Container
takes care that its
items
are instantiated if they are Config objects, but for example a Component
's
baseAction
property does not support Config objects. This is reflected in the Ext TS API by
declaring
Container.items: (Component | Config<Component>)[]
,
but
Component.baseAction: Action
(not Config<Action>
).
In other words, inadvertently using a Config object for a baseAction
results in a type error.