ryansolid / dom-expressions

A Fine-Grained Runtime for Performant DOM Rendering
MIT License
885 stars 127 forks source link

(feat) augmentable JSX.Element-types #165

Closed bigmistqke closed 2 years ago

bigmistqke commented 2 years ago

I have been having a lot of fun lately with custom JSX-elements (for example with this little side-project) : JSX are functions and functions can return more then dom-elements or any of the allowed JSXElement-types. Solidjs itself allows this approach, but it is impossible right now to properly type these components as types can not be augmented through declaration.

My proposal is to follow a pattern described https://github.com/microsoft/TypeScript/issues/28078 interface XRegistry { A:A B:B C:C } type X= XRegistry[keyof XRegistry]; ... And in the other file declare module "someModule" { interface XRegistry { D:D } }

which results in the following code: afbeelding

This way the JSXElement-type could be augmented through a declaration-file as follows afbeelding

As you can see in the following image the CustomElement-type is added to the accepted JSX.Element-types afbeelding

It creates identical code if not augmented. If you want an example of it in action: (this repo) contains a patch with it working.

bigmistqke commented 2 years ago

as discussed in the solidjs-discord by: instead of extending the JSXElement-type and obfuscating what is considered valid JSX, a following pattern can be used to bypass and extend JSXElement-type constraints without having to actually extend the types:

afbeelding

instead of returning a type which does not fit in the JSXElement-type constraints, a function is used as a container for additional data. With this approach all the usecases I had for extending JSXElement-types are solved with the added error-messages if these custom JSXElements are trying to be rendered as is.

an example of it being used in plasticine's codebase link:

afbeelding

as this technique gets a similar result to what I wanted to achieve without the added type-noise of extending solid's JSXElement-types I will close down this PR.