TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

When using react-jsx, don't treat "key" property as special unless it's specified as IntrinsicAttribute

Open dawidgarus opened this issue 1 year ago • 4 comments

🔍 Search Terms

jsx, react-jsx, key property

✅ Viability Checklist

  • [X] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [X] This wouldn't change the runtime behavior of existing JavaScript code
  • [X] This could be implemented without emitting different JS based on the types of the expressions
  • [X] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • [X] This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
  • [X] This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals

⭐ Suggestion

When "jsx" is set to "react-jsx" the key property is missing from parameters passed to jsx function and instead is passed as separate argument. For example:

<Test param="1" key="2" />

Is compiled into:

jsx_(Test, { param: '1' }, '2')

My suggestion is to ignore this behavior unless "key" property is defined as IntrinsicAttribute. Then, if key is not an intrinsic attribute, the example should compile into:

jsx_(Test, { param: '1', key: '2' })

📃 Motivating Example

It makes TSX more generic for use by any library, and less React specific

💻 Use Cases

This special treatment of "key" property is at odds with libraries other that react that DON'T treat key differently, making if effectively an restricted parameter.

As a workaround, you can merger parameters with key inside jsx function:

function jsx(name, params, key) {
  const newParams = {...params, key};
  // ...
}

But this may lead to weird special cases, like this:

<Test key="key" {...params} />

key attribute will override existing key property from params.

Please make tsx friendly for libraries other than react.

dawidgarus avatar May 19 '24 16:05 dawidgarus

It makes TSX more generic for use by any library, and less React specific

But... you specifically asked for react-jsx...

fatcerberus avatar May 19 '24 17:05 fatcerberus

It makes TSX more generic for use by any library, and less React specific

But... you specifically asked for react-jsx...

If react-jsx is to be used only with react, then why don't we have "jsxImportSource" hardcoded to "react"? Or in other words, the ONLY way to use tsx for anything other than react is to set "jsx" to "preserve", because only "preserve" doesn't have the word react in it. Is that the official stance of TypeScript?

dawidgarus avatar May 19 '24 18:05 dawidgarus

react-jsx means "compile JSX syntax using React semantics" so yes if your JSX flavor is non-React-compatible you would use preserve.

Josh-Cena avatar May 20 '24 10:05 Josh-Cena

tsx for anything other than react

View frameworks exist that are not React, not React-compatible, but still are compatible only in the jsx function.

There's also the react preset for Typescript, which transforms to a function call (usually named React.createElement or h) with slightly different children semantics, and has no special semantics for key.

nmain avatar May 20 '24 12:05 nmain

We don't do type-directed emit, which is what this is asking for.

jsx: react doesn't have the key special-casing; it's more accurately thought of as the JSX semantics of ~2016 that predate _jsx

jsx: react-jsx really does include React-specific semantics

jsx: preserve exists if neither of those work for your scenario

RyanCavanaugh avatar Jun 06 '24 19:06 RyanCavanaugh

This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

typescript-bot avatar Jun 09 '24 01:06 typescript-bot