Repository navigation
Support JSX shorthand properties, for compatibility with BunΒ #52057
Description
Activity
It's a very natural extension of the syntax, and extremely convenient too, for many components that I personally write about half of the JSX is just redundant and could be deleted if I could use shorthand properties.
As massive of an improvement it is though I can't give up type-checking for it.
I'm going to push back against both of these statements. I don't find it natural, and I don't see it as an improvement. I find the syntax noisy and annoying to scan, because now I have to add one more syntax in my head to keep track of when it comes to passing props. It might make writing props marginally easier by saving a few keystrokes, but it will make reading those props a bit more aggravating, especially in scenarios where both the shorthand and longhand are used.
The more ways you have to achieve a single task, the more complex the language becomes, and the harder it is to learn and teach. Even for somebody like me who's been writing JS professionally for 25 years, and TS since it was introduced, I'd much prefer the language move in the direction of being easier to read and understand, even if it means I have to type a few more characters.
Reacted by Max Leiter, Kenta Moriuchi, Γmer AydΔ±n, Yongbeen Im, Jack Warren, Public Profile, bai, Gaurav Kulkarni, Michael, Manuel Serra and 16 moreReacted by Muthu Kumar, Bruno Fantauzzi, Joe Ervin, Firas Alkhatib, Sebastian Kupke and Emil OngReacted by Nabila-tarasyuk commented
on Dec 30, 2022 ContributorMore actionsIs this part of the JSX specification? Or is this a
Bunspecific syntax?Reacted by Max Coplan and Xuanbo ChengI'm going to guess it's not in the spec, going by these remarks in the OP:
...even though they haven't beed added to the JSX spec, presumably because that's effectively dead.
Basically the engine I'd like to use supports it already, the code I tend to write screams for this feature, but the JSX spec is abandonware and TS doesn't support it.
Reacted by Oleksandr Tarasiuk, Max Coplan and Xuanbo Chengrossipedia (@rossipedia) Interestingly, despite the additional syntax complexity, I do find shorthand properties to mostly improve readability--in JS. They look oddly out of place in JSX, though, for whatever reason.
Reacted by rossipedia, Akash Patel, SATYAM MISHRA, Igal Klebanov and Mahesh BansodThere has been some prior discussion in react/jsx#23.
Reacted by Ryan Shaul, Eric LERY, robotkutya, stepney141, Kevin Chavez and Max CoplanMartinJohns commented
on Dec 30, 2022 ContributorMore actionsAs a workaround you can use object spreading:
const onClick = console.log; const vdom = <div {...{onClick}} />;
Works well with multiple attributes as well:
const onClick = console.log; const onBlur = console.log; const vdom = <div {...{onClick, onBlur}} />;
No idea why some people have the urge to downvote this comment when all I do is provide a viable option that already works and is supported by both JSX and TypeScript.
Reacted by Matheus Oliveira, Eric LERY, Petyo Ivanov, Isaac, Satyajit Sahoo, Chiru, Darryl Yeo, Public Profile, Torvin, Kevin Chavez and 14 moreReacted by dQw4w9WgXcQ, Eduardo Vicente, Sriram Hariharan, ail3as, James Anderson, zprjk, V, Ο Ξ, Ivo, Aras and 8 moreAs much as I agree with rossipedia (@rossipedia), the pattern Martin Johns (@MartinJohns) communicates is one I've seen quite often. In my eyes their comment is not so much a suggestion as a reminder of something that's out there being done all the time.
This has so long been a mild annoyance in JSX, and spreading is such an obvious workaround, that it's literally the first response to react/jsx#23.
Just like JavaScript when it stopped evolving in the "dark age" of IE6, people will find workarounds to common annoyances, and as long as
<div {...{onClick, onBlur}} />is valid JS people will do it. It's not sign of weak language design to add a feature like this. On the contrary. It's good language design to make it easier to do the right thing than to do the wrong thing, and{...{onClick, onBlur}}is both easy and "wrong".Reacted by Fabio Spampinato, JoΓ£o Artur, Artur MΓΌller, Mahesh Bansod and bigmistqkeAlso, there's been mumblings of JSX2 but IMO waiting for a major version to add non-breaking changes like this has disadvantages. Wondering what Sebastian MarkbΓ₯ge (@sebmarkbage) thinks
One of the major benefits of JSX is not breaking the syntax and having pretty much universal support in implementations. Although itβs not actually quite the same in all implementations.
It has allowed a lot of code to move between implementations without anyone really having to think about how amazing and unlikely that is.
I think once we pull the bandaid and accept breaking changes we can do an even better JSX. Thatβs what the JSX 2.0 concept is all about.
That said, if we design a JSX 1.5 without breaking changes, what would that look like as a whole? ES2015 was a lot of work because figuring out the interplay and where we wanted to go next was important.
What else would go into a potential JSX 1.5?
Reacted by Jarred Sumner, SATYAM MISHRA, Max Coplan, Sukka and Mahesh BansodWhat else would go into a potential JSX 1.5?
Here are a couple ideas, but you would be better at answering:
- Ship template literals support
- Spec out whitespacing / line break behaviors Β react/jsx#143. newline behavior is not consistent for string literal attribute values right now
Reacted by Eric LERY, Kevin Chavez and Mark JaquithI think this should be unchecked in the viability checklist of the original post?
This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
That should then answer the question of if this should be implemented in TypeScript at this time.
Reacted by Nicky McCurdy, Yoshiya Hinosawa, Morris Allison III and Xuanbo ChengI think the TypeScript team has made the right decision in not encouraging additional nonstandard syntax. JSX is acceptable, since it can still be strongly typed (and both JSX and Flow were designed to be compatible with this approach originally). But I don't think it's a good idea to implement JSX syntax that's not in Facebook's standard, as it will further fragment React and TypeScript tooling from tools implementing the syntax.
I think this should be unchecked in the viability checklist of the original post?
What makes it a runtime feature? The changes would impact build-time, but not runtime (
tscbut nottslib, would not modify transpiled output in an observably different way from what<div foo={foo} />does)Reacted by Ryan Carniato and Deniz GazitepeMartinJohns commented
on Dec 31, 2022 ContributorMore actionsWhat makes it a runtime feature?
The relevant parts are probably:
non-ECMAScript syntax with JavaScript output, new syntax sugar for JS
This is generally a no-go. Except for down leveling and legacy features added before this rule (e.g. enums) the TypeScript should output equivalent JavaScript. Though given the special situation that TSX is in it's not super clear if the rule applies here. After all the TSX is not compiled to JSX. (Unless you enable
preserve, then<div {onClick} />compiles to<div {...onClick} />.)When the subject of JSX extensions comes up with the TypeScript team I've seen these two statements: They want to stick to the JSX spec and align with what Babel generates. Does Babel support this feature?
Reacted by David Sherret, Mahesh Bansod and Xuanbo Chengfabiospampinato commented
on Dec 31, 2022 AuthorMore actionsWhat else would go into a potential JSX 1.5?
Sebastian MarkbΓ₯ge (@sebmarkbage) you'd possibly know best about that, but I would like whoever has the ability to ship new features here to think "shipping what when would deliver the most value to people?"
Like maybe shipping 5 things one at a time delivers more value than shipping all 5 at once but in 5 years. Or shipping 1 feature next month maybe delivers more value than shipping 20 extremely thoughful ones but in 10 years.
Reacted by John Partee and Kevin ChavezReacted by John Partee and Kevin ChavezI think this should be unchecked in the viability checklist of the original post?
What makes it a runtime feature? The changes would impact build-time, but not runtime (tsc but not tslib, would not modify transpiled output in an observably different way from what
<div foo={foo} />does)Jarred Sumner (@Jarred-Sumner) As Martin mentioned, this part "non-ECMAScript syntax with JavaScript output, new syntax sugar for JS" alludes to what "runtime feature" means. By "runtime feature", my understanding of that is any code that will be transpiled for runtime rather than code for types that will be stripped when transpiling.
This is syntax sugar that's not in the JSX spec and just because a spec becomes stagnant doesn't mean it should be abandonedβin my opinion, instead it should be resurrected. If the JSX spec is "abandonware" then the hard work should be done by getting people to adopt a forked spec rather than making unilateral moves in the ecosystem around JSX syntax. Also, it's true JSX is a bit of an exception because it's not in ecmascript, but I don't think that's an excuse to deviate from the JSX spec since many tools need to support this syntax. Making everything work well together (like TypeScript and Bun) is easier to do when everyone follows the spec.
Reacted by Nicky McCurdy and Ryan CavanaughAlso specs that are forked can be merged upstream if the core team later decides it's valuable (for example io.js merging back into Node.js after being forked to add ES6/harmony features).
- addedExternalRelates to another program, environment, or user action which we cannot control.Relates to another program, environment, or user action which we cannot control.
on Jan 4, 2023 RyanCavanaugh commented
on Jan 4, 2023 MemberMore actionsI don't think it's appropriate for TypeScript to become the de facto new manager of the JSX spec by taking suggestions like these. We don't have the resources to do that (we're very busy writing a type checker), we don't have the necessary context on which syntaxes have which critical runtime implications on React / future iterations of React / other JSX runtimes (aside: I don't believe this is "just sugar", due to questions of object identity), and we don't want to create arbitrary new work for alternate transpilers in the absence of a strong community consensus. We don't do this to JavaScript (anymore) and it doesn't make sense to starting doing this to JSX now.
even though they haven't been added to the JSX spec, presumably because that's effectively dead.
Hard disagree on this one. I've been involved in many recent conversation in the JSX spec and, as witnessed here, the JSX spec owners are very much alive and active. It's their prerogative to decline any or all new features without presumption of neglect. This feature in particular was more or less explicitly rejected react/jsx#118
If someone wants to fork the JSX spec, get another major transpiler or two on board to commit to following it, outline how the owners of that spec have a vested interest in its long-term success, and put in some new features and bugfixes, I'd be fine with that, AKA react/jsx#119. But I'm not going to do that here through adding new de facto functionality to a spec that is clearly someone else's.
Reacted by David Sherret, Roj, Remco Haszing, Bruce Pascoe, Martin Johns, Roger SchΓΆnbΓ€chler, Brian Kim, Colin McDonnell, Kenta Moriuchi, Nicky McCurdy and 4 moreReacted by syuiloFor people interested in JSX enhancements and don't mind adding another transpiler to the mix Civet could be an option. It's a language that transpiles to TypeScript and explores some new ground while aiming to remain semantically compatible and familiar. We're working out the details of how to extend JSX in line with modern sensibilities as well as provide syntactic sugar.
Some JSX features Civet supports
In order for things to become a standard or consensus they need to be explored and used in practice so if you are interested in shaping the bleeding edge of JSX check Civet out and share your thoughts.
Reacted by Erik Demaine, Adrian Wieprzkowicz, Fabio Spampinato, Oren Elbaum and ZoltΓ‘n MatΓ³kfabiospampinato commented
on Jan 5, 2023 AuthorMore actionsRyan Cavanaugh (@RyanCavanaugh) fair enough π
I don't believe this is "just sugar", due to questions of object identity
Could you expand on that? I don't see how
{foo}wouldn't just be sugar forfoo={foo}in the context of this proposal, like I'm not proposing that{foo}emebedded in JSX should be literally considered to be a JS plain object, it's just syntax.even though they haven't been added to the JSX spec, presumably because that's effectively dead.
Hard disagree on this one. I've been involved in many recent conversation in the JSX spec and, as witnessed here, the JSX spec owners are very much alive and active.
As far as I can see JSX was introduced in 2014 and never updated since, if that's correct just looking at the spec that seems indistinguishable from a dead spec, like less tangible progress than that seems impossible.
Maybe the spec is perfect as it is, maybe extreme care is being taken in preparation for the next update, whatever the case may be I think we are all eager to see an update eventually, hopefully it will actually happen.
This feature in particular was more or less explicitly rejected react/jsx#118
It looks to me like Sebastian MarkbΓ₯ge (@sebmarkbage) said the following:
I don't think I'd want this to be the solution for a JSX 2.0 world where we could make more breaking changes to avoid the superfluous punctuation. However the bar for doing something like JSX 2.0 is very high and needs to be much more carefully considered. That said, this is probably the least objectionable non-breaking change that we could reasonably easily do.
Which sounds like a "maybe" to me. And the PR was closed by its author after they didn't receive any reply for a couple of weeks after asking Seb for clarification basically.
Unless I'm misunderstanding something Seb in this very thread said that this feature may be part of some hypothetical JSX v1.5.
If anybody with control over the JSX spec could please state what the current position on this proposal is it would probably clarify the situation for everyone.
Reacted by Daniel X Moore, Diogo Kollross, bigmistqke, Bruno Fantauzzi and German JablonskiRyanCavanaugh commented
on Jan 5, 2023 MemberMore actionsCould you expand on that? I don't see how
{foo}wouldn't just be sugar forfoo={foo}in the context of this proposal,Shouldn't it be sugar for
<elem {...{foo}} />? Since I'd expect to be able to write<bar { a, b, c } />;
the same way I can in an object literal, including using spreads
<bar { a, b, ...c } />
So we have to decide if this is sugar for
<bar a={a}, b={b} { ...c } />or<bar {... { a, b, ...c }} />If you take something like this and put it through Babel
const tmp = { a, b, ...c }; const m2 = <foo {...tmp} />; const m3 = <foo a={a} b={b} {...c} />;
you'll see slightly different code generated since the native spread remains as a native spread, but the
{...c}goes through_extendswhich is in turn basically an alias forObject.assign, andObject.assignand native spread do have slightly different semantics. Maybe those differences aren't observable in practice but the burden of proof lies on the positive claim here.The same problem has come up with template string literals in JSX, where people want to write
<foo a=`literal` />which is "just sugar", but that's also a mess because of HTML entities which are interpreted in JSX string literals but not in JS template literals, so you have to decide if this is sugar for a JSX string with a template-computed value, or sugar for a JS template string, both of which have extremely strong consistency arguments in favor of them.
"This is just sugar for that" is almost always 98% true, but the other 2% matters. Different people will regularly state that something is obviously sugar for two different things which have material differences in practice. Someone (not us) needs to figure out what this syntax means and write it down so that everyone can agree on the behavior.
Reacted by David Sherret, Fabio Spampinato and Nicky McCurdyShouldn't it be sugar for <elem {...{foo}} /> ? Since I'd expect to be able to write
In bun's current implementation, we don't support multiple identifiers in one
{}, just<div {foo} />. The rationale was to keep the parser changes as simple as possible and minimize edgecases. From a DX perspective, it would be better to support multiple but I think it's still net improvement to ship without supporting itFor template literal JSX attribute values, which bun doesn't currently implement, in my opinion which is not super relevant as I am not a spec maintainer, it should not support HTML entity codes. Maybe the parser should emit a warning if they are used to explain this
Reacted by Fabio Spampinato, Sean Boult, Nicky McCurdy, Eric LERY, Andrii Oriekhov, Bruno Fantauzzi and nokaznReacted by Brian Kimtypescript-bot commented
on Jan 9, 2023 ContributorMore actionsThis issue has been marked as 'External' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
Suggestion
π Search Terms
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
Bun implements JSX shorthand properties, presumably because they are extremely convenient to use, even though they haven't been added to the JSX spec, presumably because that's effectively dead.
π Motivating Example
Example code:
Basically
{foo}is just a shorthand forfoo={foo}. The same way outside of JSX{foo}is a shorthand for{foo: foo}.π» Use Cases
It's a very natural extension of the syntax, and extremely convenient too, for many components that I personally write about half of the JSX is just redundant and could be deleted if I could use shorthand properties.
As massive of an improvement it is though I can't give up type-checking for it.
Basically the engine I'd like to use supports it already, the code I tend to write screams for this feature, but the JSX spec is abandonware and TS doesn't support it.
Can we please consider adding it and improve the lives of millions of developers? If that's not a strong argument enough can we consider adding this for compatibility with Bun?
I'd be more than happy to submit a PR for this.
//cc Jarred Sumner (@Jarred-Sumner)