-
Notifications
You must be signed in to change notification settings - Fork 78
Description
Enhancement
As part of dojo 6.0.0 we are looking at improving our types when using TSX or the v()
and w()
pragma's.
At the moment, to use a widget in a render function programmatically you use the w()
pragma like so:
render() {
return w(Something, { a: 'yo' });
}
Under the hood we pull the properties and children types off of the class. This works well in most scenario's apart from render props:
render() {
return w(Foo, {
renderer: (thing) {
// thing cannot be inferred
}
});
}
Unfortunately when using a render prop like so, the argument thing
in this case cannot be inferred as it would take multiple passes, first to infer the properties off the generic, then to infer the properties off the renderer
function (see here: microsoft/TypeScript#26418, this may change in the future)
By separating one of these passes, we can gain inference back on render props. The nicest way I can think of doing this, which also has ergonomic benefits, is to wrap the widget class into a factory. We do this kind of type factory in other places like stores to similar effect. An example of the new ergonomics:
Widget authoring:
interface FooProperties {
renderer(thing: string): DNode | DNode[];
}
class Foo extends WidgetBase<FooProperties> {
render() {
const { renderer } = this.properties;
return renderer('hello');
}
}
// this is the new important bit
export default widget(Foo);
Widget usage:
import Foo from './Foo';
export class App extends WidgetBase {
render() {
return v('div', [
Foo({
renderer(thing) {
// thing is inferred as string
}
})
]);
}
}
As you can see, it would then no longer be necessary to use the w()
pragma at all, users would just import the factory and use it. As a nice side effect it also means this formats a lot nicer than w() with prettier too (a common complaint).
The "magic" widget()
factory just factories a WNode
under the hood. We can also make this backwards compatible, so if you use a new factoried widget the old way with w()
call it would still work.