I want to be able to use the JSX syntax to build up a heterogenous tree-like data structure that is not a webpage or an HTML template - think goal trees, discrimination nets, ASTs, and other hierarchical structures. What I have so far works, but it has a bunch of ugly typecasts due to the fact that JSX.Element resists being overridden.
Here's a snippet showing what I mean:
/** @jsx createNode */
// Redefine the type of `Element`.
declare namespace JSX {
type Element = { foo: boolean };
}
// The JSX factory function
export function createNode<Props extends { [key: string]: any } = {}>(
tag: (props: Props) => JSX.Element,
props: Props | null,
...children: JSX.Element[]
): JSX.Element {
return tag(props as Props);
}
// An example component which conforms to the new JSX.Element shape.
function Test(): JSX.Element {
return {
foo: false,
};
}
// An example component which conforms to React's protocol.
function Test2() {
return {
type: '',
props: null,
key: null,
};
}
// Error: missing properties for type, props, key.
const elt = <Test />;
// Works
const elt2 = <Test2 />;
There's no React/Preact/Solid in this code, it's just pure JSX using the jsx pragma. But no matter what I try, it seems to use React's definition for the JSX type.