-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support other JSX factories #3788
Comments
To be more specific about JSX factories, I mean PS. Also the |
What'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. |
I 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. |
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 It's already type-checking against an interface, right? So, if this interface was defined by Typescript, rather than defined by an external Emit would be largely the same then, I think? Just with 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 Emitting with 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 |
Alright, so we're half-way there :-)
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 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 - |
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 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 |
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: |
I feel like I'm hearing conflicting stories here:
Okay, but:
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 @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 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 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. |
I'm going to side with @mindplay-dk and @Blesh here. @danquirk I think the way you settle this discussion is to explain to the folks here why what you're doing is any more complex than literally just dropping the string Bottom line, transforming JSX to code does not have any actual dependency on React. It's just a transformation based on a now-popular convention. What the resultant function call is named should be irrelevant, and should certainly be configurable. Given this fact, forcing another whole build step on developers seems unnecessary when you could have avoided doing so by simply removing the unnecessary coupling to the string |
I would propose a very simple solution to this to just emit react code using a specific namespace that is not "React", most likely "JSX" as this aligns with the existing JSX.IntrinsicElements etc decl. So a simple example var theDiv = <div></div> Would be exported as var theDiv = JSX.createElement("div") If I want to use this with React then I can use any number of methods in the code to alias JSX.createElement to React.createElement. Likewise I can alias to any other backend I want. In a project that is using modules this even gives me the ability to isolate the JSX createElement handler in a module specific way.... in module X it could be linked into React, in module Y it could be linked in to some other backend. Given that there is already a bunch of Typescript specific JSX configuration that is created in the JSX namespace, it seems like only a small step to just emit element creation into this namespace as well. EDIT: And yes technically you could alias the existing emitted React.createElement calls onto some other arbitrary non-React backend, but that's a bit kludgy for my liking and potentially problematic if you are mixing other parts of the React library in. Emitting to the JSX namespace just seems like a nice clean solution that clearly abstracts the Typescript JSX support off into its own neat little box, and removes any direct coupling between JSX <-> React (which was a stated design goal to begin with for TS JSX support) |
@axefrog big +1 for your last post, I couldn't have put it better myself. @rwyborn I like what you're proposing - JSX is the technology, React is just one framework (regardless of the fact that it was the first) implementing that technology. What you propose is nice, simple, clean and it's neutral. (The fact that the compiler emits the word |
We would be open to taking a PR that would allow you to specify the name of the factory to be used instead of "React", the same lookup rules still apply, i.e. the factory has to be defined in scope. |
@mhegazy I was going to look at doing this. One thing I was thinking is that rather than be a compile option the factory name would be configured through a declaration in code, exactly the same as the JSX component prop element name is currently handled (see https://github.com/Microsoft/TypeScript/wiki/JSX#attribute-type-checking). I see these 2 cases as analogous, so you would do something like: declare module JSX {
interface ElementCreateFactory {
MyCustomFactory;
}
} Agree? |
that will not work in the transpile scenario, when the compiler does not have access to all files. one of the invariant we try to maintain, is that emit is a syntactic transformation that is independent from type information. |
Ok fair enough. Compile option it is. |
@mhegazy Babel lets you specify whatever symbol you like for the transform. I'd really encourage the TypeScript team to consider separating concerns. React is not a TypeScript concern. Representing the DOM in a friendly way is (ala TSX) but there is no reason that TypeScript should be anchoring itself to something that, for all we know, could become legacy next year when the next great thing comes out. Mark my words, you'll be looking back and saying "we can't change that now, a bunch of customers are using it and we don't want to break it for them." Check out these: I'm pretty sure there are others. |
@axefrog what specific thing are you addressing there? We already have |
@RyanCavanaugh "React emit exists as a convenience for those who don't want to chain in another tool." ... what you mean to say is "React emit exists as a convenience that only people who specifically use React.js can use if they don't want to use another tool". I still cannot for the life of me figure out why it's so hard to output a function call that doesn't assume that React.js is the only game in town, or why you'd couple yourself to a single third-party rendering library when there's no good reason to do so. What are your thoughts on the fact that Babel will spit out any function call name that you want to use when transforming JSX? |
@axefrog just to chime in, I am currently working on a PR that will let you specify the emit option in exactly the same way as the "pragma" jsx option in Babel (see https://babeljs.io/docs/plugins/transform-react-jsx/ ). This would make Typescript JSX support equivalent to Babel. eta at some point, currently lower priority than my day job :) |
@axefrog When we implemented JSX support, we decided that React emit + Preserve emit was the right trade-off in terms of convenience vs the engineering effort of adding more configurability. That was informed by the number of non-React JSX consumers in the world at the time (which is honestly still pretty low) and a general desire to reduce complexity where it makes sense. Non-React consumers do seem to be on the rise and that's why we're accepting PRs to add this functionality. Again, this issue is marked Accepting PRs. If someone wants to implement this, they can. We are not opposed to allowing other factory names and we don't intend to strongly couple the compiler to any particular framework. Send us a pull request 😉 |
@RyanCavanaugh thanks, you've satisfied my argumentative urges :) |
@rwyborn are you giving this a try? I would suggest instead of |
Very good point. |
A comment from #6146 I'd like people to weigh in on How does this look? let x = <Foo />;
|
A comment from #6146:
Apparently I don't know where should I add my comment to. :p |
Maybe make it more customizable such as in: |
👍. I support @Blesh's comment: Babel uses the I setup a basic - but working - JSX to HTMLElement factory inspired by plain-jsx in TypeScript here: https://gist.github.com/Dynalon/a8790a1fa66bfd2c26e1 though I had to create a |
thanks @rwyborn! |
A library for creating templates from .tsx files instead of mustache/handlebars is available here: https://github.com/wisercoder/uibuilder |
I know i'm a bit late into this discussion, but I would like to propose a simple and generic alternative. Add a new For example,
would get transpiled into:
|
It appears this feature was eventually added as compiler option See https://www.typescriptlang.org/docs/handbook/compiler-options.html |
For those finding this in Google - Typescript 2.8 now supports the per-file jsxFactory feature mentioned a couple of times in this issue:
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html |
Seems like Babel supports other JSX factories other than
React.createElement(...)
:Here is docs from
deku
another JSX framework from Segment.ioUsing
.babelrc
: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.
The text was updated successfully, but these errors were encountered: