JSX in TypeScript
TypeScript supports JSX out of the box — the file extension is .tsx. Configuration controls how the JSX gets compiled.
The jsx option
| Value | Effect |
|---|---|
"react-jsx" | React 17+ automatic runtime. Recommended. |
"react-jsxdev" | Same, with extra dev-only warnings. |
"react" | Classic React — emits React.createElement. |
"preserve" | Keeps JSX in the output for a bundler/Babel to handle. |
tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["DOM", "ES2022"]
}
}
Typing a component
TSX
type Props = { name: string; greeting?: string };
function Greeter({ name, greeting = 'Hello' }: Props) {
return <h1>{greeting}, {name}!</h1>;
}
// or, with React's helpers:
const Greeter2: React.FC<Props> = ({ name }) => <h1>Hi, {name}</h1>;
Typing children
TSX
type CardProps = {
title: string;
children: React.ReactNode;
};
const Card: React.FC<CardProps> = ({ title, children }) => (
<section><h2>{title}</h2>{children}</section>
);
Event handlers
TSX
function Button() {
const onClick = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
console.log('clicked');
};
return <button onClick={onClick}>Click</button>;
}
Refs
TSX
const inputRef = useRef<HTMLInputElement>(null); inputRef.current?.focus();
Non-React JSX (Solid, Preact, Vue JSX)
Each framework ships a jsxImportSource setting:
tsconfig.json — Solid
{
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "solid-js"
}
}
Tip: Type assertions in
.tsx use only the as form — the <Type>value syntax clashes with JSX. One more reason to default to as everywhere.Example
Example
// tsconfig: "jsx": "react-jsx" (or "preserve" if a bundler does the transform)
//
// type Props = { name: string };
// const Greeter = ({ name }: Props) => <h1>Hi, {name}</h1>;
console.log('Components get typed via Props');
Try it Yourself »
Exercise
Modern React JSX setting value.
"jsx": "
"
Two hyphen-joined words; nine chars.
Discussion
Loading…