Add emit support for jsx/jsxs experimental jsx runtime api by weswigham · Pull Request #39199 · microsoft/TypeScript (original) (raw)
This adds two new options for the jsx
compiler option - react-jsx
, and react-jsxdev
. They use the jsx
and jsxDEV
constructors and the react/jsx-runtime
and react/jsx-dev-runtime
entrypoints, respectively. The primary differences, as noted in the linked issue, are that children
are passed as part of the props
object, and the key
is passed as a separate argument. (The jsxDEV
constructor further takes some debug data.) In addition, this adds a jsxImportSource
compiler option (and @jsxImportSource
file pragma) to control the root specifier the jsx runtime is imported from (which defaults to react
). In it's current state, I believe this is usable, but there are some known flaws:
- The checker/program need to load the
jsxImportSource
module and use it as the source for the JSX namespace automatically. Presently you need to include it in the program yourself (ie, with atypes
directive or compiler option). This is moreso a TODO for myself, since I don't think there's any question to what we should do (implicitly include the package or@types
version in the program). This is more interesting for thejsxImportSource
pragma, which, for all intents and purposes, is animport
statement. We have a lot of services for real import statements - should they be applied to the pragma, where possible? - Babel additionally supports a
jsxRuntime
pragma (with valuesclassic
orautomatic
) to swap between the old emit and the new one. This is supportable; however currently I only key our emit off thejsx
compiler option, and the presence of thejsxImportSource
pragma. - In some cases, the new transform still falls back to
createElement
(when akey
prop follows a spread) - this is a kind of soft deprecation; however it still implicitly imports the jsx runtime and pulls increateElement
. This PR does not yet do this, as, awkwardly enough, the modulecreateElement
is supposed to come from is different from thejsx-runtime
module entrypoint. I could make this work, but I think this is something we should provide some feedback on - so long as there's still acreateElement
fallback required in the API, why can't it be exported by the same entrypoint exportingjsx
orjsxDEV
? - Without an import or export, a file is not marked as a module, and will not have an import automatically added. Should this issue an error? Or should, under these
jsx
modes, the presence of a jsx tag imply module-ness?
Fixes #34547
This is currently experimental in babel, and AFAIK not yet supported in a stable version of react
; as such, we should probably continue to experiment with it for awhile before merging it into a stable release.
TL;DR
When jsx: react-jsx
(and target: esnext
) is set,
export default (props: {className: string}) =>
compiles to
import { jsx as _jsx } from "react/jsx-runtime"; export default (props) => _jsx("div", Object.assign({ className: props.className }, { children: "childtext" }), "stablekey");