ryansolid / babel-plugin-jsx-dom-expressions

A JSX to DOM plugin that wraps expressions for fine grained change detection
MIT License
60 stars 10 forks source link

Proposal for adapting the JSX.Element type #16

Closed bluenote10 closed 5 years ago

bluenote10 commented 5 years ago

This is a translation of your statement on Gitter into TypeScript:

we aren't sending back just HTML elements anymore. We can return Arrays or Functions.. eventually everything boils down to strings or HTMLElements. But there may be any level of nested Arrays/function calls in between

The new type allows for such recursions (using this pattern). A few examples:

// The automatically inferred types in all of the following is JSX.Element as desired:
function A() {
  return <div></div>
}

let a1 = <div></div>
let a2 = <A/>
let a3 = <></>

// All of the following compiles, i.e., arbitrary nesting is supported by JSX.Element:
function Explicit1(): JSX.Element {
  return document.createElement("div");
}
function Explicit2(): JSX.Element {
  return [
    document.createElement("div"),
    document.createElement("div"),
  ];
}
function Explicit3(): JSX.Element {
  return () => document.createElement("div");
}
function Explicit4(): JSX.Element {
  return () => [
    document.createElement("div"),
    [
      document.createElement("div"),
      document.createElement("div"),
      () => document.createElement("div"),
    ],
    () => document.createElement("div"),
  ]
}

// As desired, diverging for the supported values results in compile time errors.
// For example, the following errors would be caught by the compiler:
function Rejected1(): JSX.Element {
  return 42;
}

function Rejected2(): JSX.Element {
  return "not a supported JSX element";
}

Open questions:

The follow up step of this would be to basically replace all any by JSX.Element in solid/dom.

ryansolid commented 5 years ago

Are the last 2 "Rejected" actual errors though. I realize from a "Component" mentality perhaps they are, but I handle anything that can be coerced to a string. Basically Components are just functions with a specific syntax they aren't any real type. Their return value can be a number or string.

Maybe I was wrong to think that it all it could something specific. Like look at the way I use the Match element in control flow. It returns an object. Which then becomes an array of objects due to multiple nested children. And then is run through JS function in the parent Switch component. This is pretty hairy in that those children could never be inserted in the DOM but can serve a purpose for passing data back to the parent. Is that just too weird?

Support for SVG is a good thing. I haven't handled specific cases but it should work in the basic case I believe, and it's an area I see growing in the future.

bluenote10 commented 5 years ago

Are the last 2 "Rejected" actual errors though. I realize from a "Component" mentality perhaps they are, but I handle anything that can be coerced to a string. Basically Components are just functions with a specific syntax they aren't any real type. Their return value can be a number or string.

If number and string are officially supported we can of course add them (although sometimes less is more, comes with a small bug potential). All we should try to avoid is to have any in the list, because that would prevent catching real bugs. For instance, imaging there is an array of arbitrary data objects, and the user's intention is to map over them, gets it wrong, and instead of a compile time error, it becomes a runtime surprise.

Maybe I was wrong to think that it all it could something specific. Like look at the way I use the Match element in control flow. It returns an object. Which then becomes an array of objects due to multiple nested children. And then is run through JS function in the parent Switch component. This is pretty hairy in that those children could never be inserted in the DOM but can serve a purpose for passing data back to the parent. Is that just too weird?

Yes, Match seems to be the exception than. But that should also not be a problem. I've adapted the type definitions to your feedback.

ryansolid commented 5 years ago

Yeah I mean I could have done Match a different way. I thought it was interesting to pass data through JSX. React allows that does it not? I guess this should be fine for now. A big motivator for this change was to open the system up. I was thinking it would be really cool for people to do things with Components I haven't even thought about. But cross that bridge when we get there I suppose.