Repository navigation
Support other JSX factories #3788
Description
Activity
- changed the title
[-]Support other JSX expansions[/-][+]Support other JSX factories[/+]on Jul 9, 2015 To be more specific about JSX factories, I mean
React.createElementis switched with whatever specified factory function. All the other rewires like attributes etc. remains the same. So I guess this is a small change.PS. Also the
jsx-transformsupports other factory functions: https://github.com/alexmingoia/jsx-transformWhat's the status of this?
I'm creating right now a JSX framework. Though I'm using a dirty trick with reusing React's namespaces.
RyanCavanaugh commented
on Jul 31, 2015 MemberMore actionsI think we're mostly waiting for feedback. There have been some other JSX emit suggestions and we'll need to prioritize based on how necessary (un-work-around-able) and useful they are.
- addedNeeds ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.This issue needs a plan that clarifies the finer details of how it could be implemented.
on Jul 31, 2015 Yeah, I am really excited about this feature and was trying it out with MS Code tonight - but then realized, two options for JSX processing, one just passes through JSX tags unprocessed, and the other is hard-wired to React... I don't want React - I want something lightweight. Like, for one, I was hoping maybe riotjs could be supported. Moreover, I don't want to be tied to any particular implementation.
Sounds like you're already aware of that though? :-)
How about providing a compiler (and
tsconfig.json) switch that allows you to specify which implementation to use?It's already type-checking against an interface, right?
So, if this interface was defined by Typescript, rather than defined by an external
React.d.tsfile, we could then implement this interface, specify the name of the implementation, and have the compiler type-check against an implementation of our choice?Emit would be largely the same then, I think? Just with
XYZ.instead ofReact.and type-checking against the specified implementation.I think per-project (e.g. compiler-level) is fine, and much simpler than e.g. allowing you to somehow switch implementations on a per-file basis or something - I don't imagine you'd need/want to use more than one implementation in the same project (?)
I'm really excited about this feature!
Hope is arrives in a form that is also useful to non-Reacters. (Reactionist? Reactioners? Whatever.)
Type checking is not tied to any framework; type checking is driven by
JSXnamepsace declaration (see wiki page for more details).Emitting with
-jsx preservewill result in emitting your jsx into the output after transforming any TS specific concepts, e.g. internal modules, rewriting let and const, module imports, etc..Any JSX library out there already has a compiler that supports transpiling jsx into their supported output. riotjs as well provides a compiler. the integration scenarios with TS is straight forward and with a very low over head.
For maintenance reasons, the typescript team would not want to take on the responsibility of emitting to multiple frameworks. we do care that these scenarios do work though, and the
--jsx preserveis mainly for this.Type checking is not tied to any framework; type checking is driven by
JSXnamepsace declarationAlright, so we're half-way there :-)
For maintenance reasons, the typescript team would not want to take on the responsibility of emitting to multiple frameworks
That's not really what I'm asking for - literally all I'm asking is for, is to avoid the extra compile step in a second compiler, by allowing us to replace the emitted
React.with something else. Why does that add any maintenance burden on your part?I'd really like to avoid relying on a second compiler/tool - for one, how would that work in terms of source maps? You'd need to recursively resolve source-maps from one compiler via source-maps from another compiler? Or the second compiler would need to support source-maps and resolve references while compiling? That doesn't sound simple.
I would strongly prefer to leverage the JSX compiler built into my language -
preservedoes not sound like a good option.There are other parts of the emitter than the name of the variable. for instance, in React, tag names starting with lower case, are treated as built in and always emitted as strings, where as uppercase ones are not. similarly, white spaces has its own rules in react emit. there is also serializing strings, etc.. I would expect frameworks to have differences, and I will find it misleading to say that we support other frameworks, where in fact we do not.
I would expect frameworks to have differences, and I will find it misleading to say that we support other frameworks, where in fact we do not.
I see. That's a shame. I thought the goal was to be a general-purpose programming language - now it sounds like Typescript is actually part framework and part language, or at the very least, it's now tailored for one particular framework.
I think that's a very odd decision - instead of building a feature that could be generally useful and enable people to do new and original things, possibly catering to a lot more people and a lot of new ideas, you chose one specific framework, which seems really opinionated.
Just my opinion of course, but frameworks generally have a substantially shorter life-span than languages. IMO, this is going to to shorten the shelf-life of Typescript tremendously. I really wish you had made something that everyone could enjoy, regardless of their taste in frameworks...
If you peruse the various discussions in issues like #3203 you'll see that quite a bit of effort and thought went into making the JSX support as generalized as possible while also supporting the primary use case of today (React). There is very little coupling and as noted with
--jsx preserveit's very possible to run a second tool over your output to get the emit you need for the framework of choice.If I had a request, it would be to please stick to what Babel has already done in this area.
For example a comment at the top of a file can be used to adjust output as well:
/** @jsx h */changes it toh('pre', {}, [])Reacted by Erin Dachtler, Chris Davies and Marius SchulzI feel like I'm hearing conflicting stories here:
the typescript team would not want to take on the responsibility of emitting to multiple frameworks
Okay, but:
quite a bit of effort and thought went into making the JSX support as generalized as possible
So what are you saying, folks?
JSX support should be generalized, but you want to emit for only one framework?
I'm afraid I don't follow. There's nothing general about supporting one select framework - that is, by my definition, the opposite of general.
To clarify, I'm not asking you to support other frameworks - I'm asking you to make this feature configurable enough to allow the community to implement support for other frameworks. I'm suggesting that making the hard-coded
Reactreference configurable is one way to do that. It doesn't make you responsible for integration with any other frameworks, I don't believe anybody would assume that - but it would permit others to do so, without feeling like they have to "hack" Typescript or "polyfill" React.Dan Quirk (@danquirk) I did follow these discussion, and I participated in another thread than the one you mentioned above. I didn't feel like like anyone was listening though, which was odd, a bit of a let-down, and btw the only time I've ever participated in these discussions and felt like I was being ignored. It was my impression that minds were already made up and perhaps React was too popular a force to go up against. I still feel that way. As someone at my office remarked today, Typescript is now actually a framework and not just a language, which is kind of sad...
It is entirely possible to make the feature support extension without taking on the cost of that support ourselves. You could imagine a world where
--jsx preservedidn't exist, and we literally did only and always translate JSX elements to React calls. Likewise you can imagine a world where we baked in React typing definitions in such a way that alternative JSX based frameworks wouldn't be as easily used.To clarify, I'm not asking you to support other frameworks - I'm asking you to make this feature configurable enough to allow the community to implement support for other frameworks. I'm suggesting that making the hard-coded React reference configurable is one way to do that. It doesn't make you responsible for integration with any other frameworks, I don't believe anybody would assume that - but it would permit others to do so, without feeling like they have to "hack" Typescript or "polyfill" React.
I understand the ask here, but can you clarify why
--jsx preserveand a post build step doesn't do what you want? I get that it'd be simpler to just have a compiler flag/option to do the job rather than some separate tool but the end result is the same no? What rules in our current JSX support are actually blocking your use of riotjs (or whatever alternative you have in mind)? I think that's where the confusion is occurring. You're claiming we haven't made a generalized solution that supports other frameworks because it isn't supported in one particular way (a compiler flag) but we simply opted for a different way (at least for now) that accomplishes the same goal (hopefully).As far as past discussions go, I'm sorry if you didn't feel heard. We definitely read all the feedback here and take it into consideration whether in explicit design meetings or random ruminations at our desks. Particularly for some of the larger discussions that occur over a long time frame (JSX, non-nullable types, etc) the GitHub discussion format breaks down a bit and it becomes difficult to track/keep up with in a satisfactory way. Sometimes I come in in the morning to many pages of new comments on an issue where I wish there was some forked/threaded view (a la reddit) because otherwise responding to older comments ends up making the whole thread a difficult to read, endless circle (the non-nullable type issue is a big offender here). Perhaps for some larger items we can consider alternate means of sharing and commenting on ideas/specs so we get more precision (ex ability to annotate individual sentences with a single relevant question) and less of everyone having to write small essays back and forth.
Reacted by Alex17 remaining items
Rowan Wyborn (@rwyborn) are you giving this a try? I would suggest instead of
JSX.createElement(...), it is better named asJSX.compose(...)so it would be more generic. Not alljsxcompose to a DOM/VirtualDOM element.
They simply convert to a compilation target that can be understand by the respective framework.Not all jsx compose to a DOM/VirtualDOM element.
Very good point.
RyanCavanaugh commented
on Dec 18, 2015 MemberMore actionsA comment from #6146 I'd like people to weigh in on
How does this look?
let x = <Foo />;
--jsx preservelet x = <Foo />;
--jsx reactlet x = React.createElement(Foo);
--jsx react --reactNamespace rtlet x = rt.createElement(Foo);
--jsx makelet x = make(Foo);
Reacted by Erin Dachtler, spion and MartynasA comment from #6146:
I would suggest to "pollute the global" with a meaningful namespace, such as
JSX.make()orJSX.compose(). But simplemake()might work too, just that it is a bit less convenience when I customize it in code (i.e. couldn't have a proper singleton such asJSXto hold states, when needed).Apparently I don't know where should I add my comment to. :p
Maybe make it more customizable such as in:
https://github.com/alexmingoia/jsx-transform👍. I support Blesh's comment: Babel uses the
/** @jsx: factoryFn */syntax which is quite handy. A compiler flag would also be great. If support for this lands in TS (as in Babel), I can see a whole new way of creating templates from .tsx files instead of mustache/handlebars etc:I setup a basic - but working - JSX to HTMLElement factory inspired by plain-jsx in TypeScript here: https://github.com/proxy/gist.github.com/Dynalon/a8790a1fa66bfd2c26e1 though I had to create a
Reactshim so that it compiles with TS 1.7.5.Reacted by Erin Dachtler and Marius Schulz- addedFixedA PR has been merged for this issueA PR has been merged for this issue
on Jan 7, 2016 thanks Rowan Wyborn (@rwyborn)!
A library for creating templates from .tsx files instead of mustache/handlebars is available here: https://github.com/wisercoder/uibuilder
This takes advantage of the new reactNamespace flag of TypeScript 1.8I know i'm a bit late into this discussion, but I would like to propose a simple and generic alternative. Add a new
literalemit mode which transpiles the JSX expressions into object literals. This would make the output highly reusable in any custom JSX framework without dependencies on any predefined factory methods.For example,
<MyComponent attr1="value1"> <div class="style1"> <SubComponent attr2="value2"/> </div> </MyComponent>would get transpiled into:
{ "type": MyComponent, "attributes": { "attr1": "value1" }, "children": [ { "type": "div", "attributes": { "class": "style1" }, "children": [ { "type": SubComponent, "attributes": { "attr2": "value2" } } ] } ] }Reacted by Tony Bradley, Marvin Hagemeister, Nikolay Nadorichev, Antanas A. and Rob EisenbergIt appears this feature was eventually added as compiler option
--jsxFactorySee https://www.typescriptlang.org/docs/handbook/compiler-options.html
Reacted by bykbtzrFor those finding this in Google - Typescript 2.8 now supports the per-file jsxFactory feature mentioned a couple of times in this issue:
/** @jsx dom */https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html
Reacted by Moacir Braga- locked and limited conversation to collaborators
on Jul 25, 2018
Seems like Babel supports other JSX factories other than
React.createElement(...):Here is docs from
dekuanother JSX framework from Segment.ioUsing
.babelrc:{ "jsxPragma": "element" }Source: https://github.com/dekujs/deku/blob/master/docs/guides/jsx.md#babelrc
I propose we add something similar to the TS compiler options. Letting people to do a post build of preserved JSX element is not the nicest solution.