JSMonk / hegel

An advanced static type checker
https://hegel.js.org
MIT License
2.1k stars 59 forks source link

Hegel and JSX #37

Open unrealsolver opened 4 years ago

unrealsolver commented 4 years ago

How could we accomplish Hegel to work with JSX?

JSMonk commented 4 years ago

Currently, Hegel doesn't work with JSX, but it will work

trusktr commented 4 years ago

If Hegel adopts JSX (which would be awesome!), please take a look at these TypeScript issues:

The TLDR of those issue is that JSX is merely a language feature, and various tools and libraries give JSX different meaning.

Some tools, for example, compile JSX to DOM expressions. In the statement

const div = <div>hello</div>
const div = <p><span>world</span></p>

it would be great to be able to configure Hegel (either with types in code or specifying types in a config file, or something) so that the div variable is inferred to be of type HTMLDivElement and p is inferred to be of type HTMLParagraphElement.

To take the idea further, maybe there could be (for exampe), a type error if a HTMLSelectElement is passed children that aren't HTMLOptionElement or HTMLOptGroupElement.

In TypeScript currently, JSX expressions have only one type, JSX.Element (which can be defined in the environment by the TypeScript user, and the react lib defines it if you have it installed), and the JSX mechanism is generally geared towards React and React-like vdom-factory libs.

If Hegel will add JSX, there's a chance here to do it a better way than with TypeScript, making it more generic and useful for a variety of use cases.

cc @ryansolid

JSMonk commented 4 years ago

@trusktr. Thank you a lot ❤️ . It will really help us to implement better JSX support.

dmisdm commented 4 years ago

Framework-agnostic JSX would be so nice! You might not want to overload this feature, but, here's another use-case: https://emotion.sh/docs/css-prop tl;dr; it's currently possible in TS to augment JSX.IntrinsicAttributes or similar interfaces in order to add global props, which are expected to be transformed by a macro or plugin. The props that actually get rendered might not be the same as the ones written in the source. Using the css prop in your source might result in using className at runtime...so it might get dicey in terms of type soundness...maybe it's just not worth the trouble.

trusktr commented 4 years ago

We can make the same assumption with JSX output as with any other JS output from TS: people will write JSX (or JS) with type safety, and then view the result in the browser, without muddling with the output. They will rely on TS type checking the source, without caring about the output.

thecotne commented 4 years ago

we can just add @babel/plugin-transform-react-jsx plugin and most of jsx will work without much effort

also type system will have same behaviour on jsx and React.createElement code

Screen Shot 2020-06-22 at 07 33 38
ryansolid commented 4 years ago

Yeah.. although I believe that brings most of the React-isms with it. It's a path. But it feels like TypeScript has been spending the last couple years trying to backtrack from those early only consider React decisions. The JSX spec goes well beyond what React uses and that transformation. Things like attribute namespaces come to mind (which would be really useful for Vue or Svelte like templating). Or even how awkward it has been to add a universal approach to fragments. The quite literally goes on and on.

thecotne commented 4 years ago

@ryansolid if we make plugins used by hegel configurable we can support any number of frameworks/libraries

for example with babel-plugin-jsx-dom-expressions we can support DOM Expressions like so

Screen Shot 2020-06-22 at 08 06 10
trusktr commented 4 years ago

we can just add @babel/plugin-transform-react-jsx plugin and most of jsx will work without much effort

Add it to Hegel? Or add it to an app's particular build pipeline?

I think it would be neat if a tool like Hegel had Babel support built in (to some degree?), so we could have both type safety and choice of (JSX) output all in one tool.

thecotne commented 4 years ago

@trusktr hegel is using babel parser and babel AST so babel plugins can be used as well

peter-leonov commented 4 years ago

As far as I understand, Hegel’s model is very close to Flow’s one: it provides the type system only relying on Babel build pipeline to transpile the code for use in browsers and node.

Btw, while using Flow I always missed the support for Babel plugins at the type level. This blocked my team from experimenting with cutting edge language features and making our own little tweaks (say for testing).

hinell commented 4 years ago

@JSMonk I think it's best to let handle JSX to a well established tools like babel via webpack or alike and provide only type checks.

trusktr commented 4 years ago

@JSMonk I think it's best to let handle JSX by a well established tools like babel via webpack or alike and provide only type checks.

Considering Hegel already uses Babel, maybe Hegel can just add a config option that allows the user to specify Babel presets/plugins that are used after Hegel has finished type checking and after Hegel's transform. Or maybe Hegel can only strip types (after type checking), and allow the user to specify all of the Babel transforms (overriding the default).