Skip to content

Support other JSX factories #3788

Description

@tinganho

Seems like Babel supports other JSX factories other than React.createElement(...):

Here is docs from deku another JSX framework from Segment.io
Using .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.

Activity

  1. changed the title [-]Support other JSX expansions[/-] [+]Support other JSX factories[/+] on Jul 9, 2015
  2. tinganho commented on Jul 9, 2015

    @tinganho
    ContributorAuthor

    To be more specific about JSX factories, I mean React.createElement is 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-transform supports other factory functions: https://github.com/alexmingoia/jsx-transform

  3. tinganho commented on Jul 31, 2015

    @tinganho
    ContributorAuthor

    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.

  4. RyanCavanaugh commented on Jul 31, 2015

    @RyanCavanaugh
    Member

    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.

  5. added
    Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.
    on Jul 31, 2015
  6. mindplay-dk commented on Sep 8, 2015

    @mindplay-dk

    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.ts file, 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 of React. 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.)

  7. mhegazy commented on Sep 8, 2015

    @mhegazy
    Contributor

    Type checking is not tied to any framework; type checking is driven by JSX namepsace declaration (see wiki page for more details).

    Emitting with -jsx preserve will 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 preserve is mainly for this.

  8. mindplay-dk commented on Sep 9, 2015

    @mindplay-dk

    Type checking is not tied to any framework; type checking is driven by JSX namepsace declaration

    Alright, 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 - preserve does not sound like a good option.

  9. mhegazy commented on Sep 9, 2015

    @mhegazy
    Contributor

    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.

  10. mindplay-dk commented on Sep 9, 2015

    @mindplay-dk

    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...

  11. danquirk commented on Sep 9, 2015

    @danquirk
    Member

    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 preserve it's very possible to run a second tool over your output to get the emit you need for the framework of choice.

  12. benlesh commented on Sep 9, 2015

    @benlesh

    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 to h('pre', {}, [])

  13. mindplay-dk commented on Sep 10, 2015

    @mindplay-dk

    I 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 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.

    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...

  14. danquirk commented on Sep 10, 2015

    @danquirk
    Member

    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 preserve didn'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 preserve and 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.

  15. 17 remaining items

  16. unional commented on Dec 17, 2015

    @unional
    Contributor

    Rowan Wyborn (@rwyborn) are you giving this a try? I would suggest instead of JSX.createElement(...), it is better named as JSX.compose(...) so it would be more generic. Not all jsx compose to a DOM/VirtualDOM element.
    They simply convert to a compilation target that can be understand by the respective framework.

  17. mindplay-dk commented on Dec 17, 2015

    @mindplay-dk

    Not all jsx compose to a DOM/VirtualDOM element.

    Very good point.

  18. RyanCavanaugh commented on Dec 18, 2015

    @RyanCavanaugh
    Member

    A comment from #6146 I'd like people to weigh in on


    How does this look?

    let x = <Foo />;
    • --jsx preserve
      • let x = <Foo />;
    • --jsx react
      • let x = React.createElement(Foo);
    • --jsx react --reactNamespace rt
      • let x = rt.createElement(Foo);
    • --jsx make
      • let x = make(Foo);
  19. unional commented on Dec 18, 2015

    @unional
    Contributor

    A comment from #6146:

    I would suggest to "pollute the global" with a meaningful namespace, such as JSX.make() or JSX.compose(). But simple make() 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 as JSX to hold states, when needed).

    Apparently I don't know where should I add my comment to. :p

  20. unional commented on Jan 2, 2016

    @unional
    Contributor

    Maybe make it more customizable such as in:
    https://github.com/alexmingoia/jsx-transform

  21. Dynalon commented on Jan 7, 2016

    @Dynalon

    👍. 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 React shim so that it compiles with TS 1.7.5.

  22. mhegazy commented on Jan 7, 2016

    @mhegazy
    Contributor
  23. wisercoder commented on Mar 7, 2016

    @wisercoder

    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.8

  24. gilboa23 commented on Jun 15, 2016

    @gilboa23

    I know i'm a bit late into this discussion, but I would like to propose a simple and generic alternative. Add a new literal emit 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" 
                      }
                   }
                ]
             }
          ]
       }
    
  25. mrcrowl commented on May 24, 2017

    @mrcrowl

    It appears this feature was eventually added as compiler option --jsxFactory

    See https://www.typescriptlang.org/docs/handbook/compiler-options.html

  26. ravihugo commented on Apr 1, 2018

    @ravihugo

    For 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

  27. locked and limited conversation to collaborators on Jul 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixedA PR has been merged for this issueHelp WantedYou can do thisSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions