You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: packages/documentation/copy/en/reference/JSX.md
+92-15Lines changed: 92 additions & 15 deletions
Original file line number
Diff line number
Diff line change
@@ -18,8 +18,7 @@ In order to use JSX you must do two things.
18
18
1. Name your files with a `.tsx` extension
19
19
2. Enable the [`jsx`](/tsconfig#jsx) option
20
20
21
-
TypeScript ships with three JSX modes: `preserve`, `react`, and `react-native`.
22
-
These modes only affect the emit stage - type checking is unaffected.
21
+
TypeScript ships with several JSX modes: `preserve`, `react` (classic runtime), `react-jsx` (automatic runtime), `react-jsxdev` (automatic development runtime), and `react-native`.
23
22
The `preserve` mode will keep the JSX as part of the output to be further consumed by another transform step (e.g. [Babel](https://babeljs.io/)).
24
23
Additionally the output will have a `.jsx` file extension.
25
24
The `react` mode will emit `React.createElement`, does not need to go through a JSX transformation before use, and the output will have a `.js` file extension.
@@ -70,14 +69,73 @@ This is important for two reasons:
70
69
TypeScript uses the [same convention that React does](http://facebook.github.io/react/docs/jsx-in-depth.html#html-tags-vs.-react-components) for distinguishing between these.
71
70
An intrinsic element always begins with a lowercase letter, and a value-based element always begins with an uppercase letter.
72
71
72
+
### The `JSX` namespace
73
+
74
+
JSX in TypeScript is typed by the `JSX` namespace. The `JSX` namespace may be defined in various places, depending on the `jsx` compiler option.
75
+
76
+
The `jsx` options `preserve`, `react`, and `react-native` use the type definitions for classic runtime. This means a variable needs to be in scope that’s determined by the `jsxFactory` compiler option. The `JSX` namespace should be specified on the top-most identifier of the JSX factory. For example, React uses the default factory `React.createElement`. This means its `JSX` namespace should be defined as `React.JSX`.
77
+
78
+
```ts
79
+
exportfunction createElement():any;
80
+
81
+
exportnamespaceJSX {
82
+
// …
83
+
}
84
+
```
85
+
86
+
And the user should always import React as `React`.
87
+
88
+
```ts
89
+
import*asReactfrom'react';
90
+
```
91
+
92
+
Preact uses the JSX factory `h`. That means its types should be defined as the `h.JSX`.
93
+
94
+
```ts
95
+
exportfunction h(props:any):any;
96
+
97
+
exportnamespaceh.JSX {
98
+
// …
99
+
}
100
+
```
101
+
102
+
The user should use a named import to import `h`.
103
+
104
+
```ts
105
+
import { h } from'preact';
106
+
```
107
+
108
+
For the `jsx` options `react-jsx` and `react-jsxdev`, the `JSX` namespace should be exported from the matching entry points. For `react-jsx` this is `${jsxImportSource}/jsx-runtime`. For `react-jsxdev`, this is `${jsxImportSource}/jsx-dev-runtime`. Since these don’t use a file extension, you must use the [`exports`](https://nodejs.org/api/packages.html#exports) field in `package.json` map in order to support ESM users.
109
+
110
+
```json
111
+
{
112
+
"exports": {
113
+
"./jsx-runtime": "./jsx-runtime.js",
114
+
"./jsx-dev-runtime": "./jsx-dev-runtime.js",
115
+
}
116
+
}
117
+
```
118
+
119
+
Then in `jsx-runtime.d.ts` and `jsx-dev-runtime.d.ts`:
120
+
121
+
```ts
122
+
exportnamespaceJSX {
123
+
// …
124
+
}
125
+
```
126
+
127
+
Note that while exporting the `JSX` namespace is sufficient for type checking, the production runtime needs the `jsx`, `jsxs`, and `Fragment` exports at runtime, and the development runtime needs `jsxDEV` and `Fragment`. Ideally you add types for those too.
128
+
129
+
If the `JSX` namespace isn’t available in the appropriate location, both the classic and the automatic runtime fall back to the global `JSX` namespace.
130
+
73
131
### Intrinsic elements
74
132
75
133
Intrinsic elements are looked up on the special interface `JSX.IntrinsicElements`.
76
134
By default, if this interface is not specified, then anything goes and intrinsic elements will not be type checked.
77
135
However, if this interface _is_ present, then the name of the intrinsic element is looked up as a property on the `JSX.IntrinsicElements` interface.
78
136
For example:
79
137
80
-
```ts
138
+
```tsx
81
139
declarenamespaceJSX {
82
140
interfaceIntrinsicElements {
83
141
foo:any;
@@ -104,7 +162,7 @@ declare namespace JSX {
104
162
105
163
Value-based elements are simply looked up by identifiers that are in scope.
106
164
107
-
```ts
165
+
```tsx
108
166
importMyComponentfrom"./myComponent";
109
167
110
168
<MyComponent />; // ok
@@ -123,7 +181,7 @@ Because these two types of value-based elements are indistinguishable from each
123
181
As the name suggests, the component is defined as a JavaScript function where its first argument is a `props` object.
124
182
TS enforces that its return type must be assignable to `JSX.Element`.
The element instance type is interesting because it must be assignable to `JSX.ElementClass` or it will result in an error.
212
270
By default `JSX.ElementClass` is `{}`, but it can be augmented to limit the use of JSX to only those types that conform to the proper interface.
213
271
214
-
```ts
272
+
```tsx
215
273
declarenamespaceJSX {
216
274
interfaceElementClass {
217
275
render:any;
@@ -244,7 +302,7 @@ This is slightly different between intrinsic and value-based elements.
244
302
245
303
For intrinsic elements, it is the type of the property on `JSX.IntrinsicElements`
246
304
247
-
```ts
305
+
```tsx
248
306
declarenamespaceJSX {
249
307
interfaceIntrinsicElements {
250
308
foo: { bar?:boolean };
@@ -262,7 +320,7 @@ It should be declared with a single property.
262
320
The name of that property is then used.
263
321
As of TypeScript 2.8, if `JSX.ElementAttributesProperty` is not provided, the type of first parameter of the class element's constructor or Function Component's call will be used instead.
264
322
265
-
```ts
323
+
```tsx
266
324
declarenamespaceJSX {
267
325
interfaceElementAttributesProperty {
268
326
props; // specify the property name to use
@@ -283,7 +341,7 @@ class MyComponent {
283
341
The element attribute type is used to type check the attributes in the JSX.
You can specify the type of _children_ like any other attribute. This will override the default type from, e.g. the [React typings](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react) if you use them.
347
405
348
-
```ts
406
+
```tsx
349
407
interfacePropsType {
350
408
children:JSX.Element
351
409
name:string
@@ -386,11 +444,30 @@ You can customize the type by specifying the `JSX.Element` interface.
386
444
However, it is not possible to retrieve type information about the element, attributes or children of the JSX from this interface.
387
445
It is a black box.
388
446
447
+
## The JSX function return type
448
+
449
+
By default, function components must return `JSX.Element | null`. However, this doesn’t always represent runtime behaviour. As of TypeScript 5.1, you can specify `JSX.ElementType` to override what is a valid JSX component type. Note that this doesn’t define what props are valid. The type of props is always defined by the first argument of the component that’s passed. The default looks something like this:
0 commit comments