jsx în TypeScript

Spune ce face tsc cu sintaxa JSX din fișierele .tsx: o transformă în apeluri de funcții (React) sau o lasă neschimbată.

Sintaxă
"compilerOptions": { "jsx": "react-jsx" }

tsc --jsx react-jsx

Ce face jsx

JSX (<p>Bună</p>) poate fi scris doar în fișiere .tsx. Fără jsx, tsc dă eroarea TS17004. Valoarea aleasă decide cum arată rezultatul: react-jsx (React 17+) transformă fiecare element în _jsx("p", ...) și adaugă singur importul din react/jsx-runtime; react (forma clasică) produce React.createElement(...) și cere ca React să fie în scope.

preserve lasă JSX-ul neschimbat și scrie fișiere .jsx, pentru o altă unealtă care face transformarea. react-native păstrează JSX-ul, dar scrie .js. react-jsxdev este varianta de dezvoltare a lui react-jsx, cu numele fișierului și rândul pentru mesaje de eroare mai clare.

Nu are valoare implicită (JSX nu este permis). tsc --init din 5.9 scrie "jsx": "react-jsx". În proiecte cu Vite sau Next.js, tsc doar verifică (noEmit), iar jsx trebuie totuși setat (de obicei react-jsx sau preserve).

Parametri

Parametru Descriere
react-jsx Transformă JSX în _jsx()/_jsxs(), cu import automat (React 17+).
react-jsxdev Ca react-jsx, cu informații pentru depanare.
react Transformă JSX în React.createElement().
preserve Lasă JSX-ul neschimbat; scrie .jsx.
react-native Lasă JSX-ul neschimbat; scrie .js.

Exemple

Exemplul 1: react-jsx

Importul din react/jsx-runtime este adăugat automat. Textul românesc din JSX este scris cu secvențe \u.

// tsconfig.json
{
  "compilerOptions": {
    "target": "es2022",
    "module": "esnext",
    "jsx": "react-jsx",
    "outDir": "dist"
  }
}

// src/salut.tsx
export function Salut({ nume }: { nume: string }) {
  return <p className="salut">Bună, {nume}!</p>;
}

export const Lista = () => (
  <>
    <Salut nume="Ana" />
    <Salut nume="Ion" />
  </>
);

Rezultat (tsc 5.9)

$ npx tsc && cat dist/salut.js
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
export function Salut({ nume }) {
    return _jsxs("p", { className: "salut", children: ["Bun\u0103, ", nume, "!"] });
}
export const Lista = () => (_jsxs(_Fragment, { children: [_jsx(Salut, { nume: "Ana" }), _jsx(Salut, { nume: "Ion" })] }));

Exemplul 2: react și preserve

Același fișier, cu "jsx": "react" și apoi cu "jsx": "preserve" (care scrie dist/salut.jsx).

// tsconfig.json: "jsx": "react", apoi "jsx": "preserve"

Rezultat (tsc 5.9)

$ npx tsc && cat dist/salut.js          # "jsx": "react"
export function Salut({ nume }) {
    return React.createElement("p", { className: "salut" },
        "Bun\u0103, ",
        nume,
        "!");
}
export const Lista = () => (React.createElement(React.Fragment, null,
    React.createElement(Salut, { nume: "Ana" }),
    React.createElement(Salut, { nume: "Ion" })));

$ npx tsc && cat dist/salut.jsx         # "jsx": "preserve"
export function Salut({ nume }) {
    return <p className="salut">Bună, {nume}!</p>;
}
export const Lista = () => (<>
    <Salut nume="Ana"/>
    <Salut nume="Ion"/>
  </>);

Exemplul 3: Fără jsx

Fișierul .tsx conține JSX, dar jsx nu este setat.

// tsconfig.json
{
  "compilerOptions": {
    "target": "es2022",
    "module": "esnext",
    "noEmit": true
  }
}

Rezultat (tsc 5.9)

$ npx tsc
src/salut.tsx(2,10): error TS17004: Cannot use JSX unless the '--jsx' flag is provided.
src/salut.tsx(6,3): error TS17004: Cannot use JSX unless the '--jsx' flag is provided.
src/salut.tsx(7,5): error TS17004: Cannot use JSX unless the '--jsx' flag is provided.
src/salut.tsx(8,5): error TS17004: Cannot use JSX unless the '--jsx' flag is provided.

Greșeli frecvente

  • Să scrii JSX într-un fișier .ts. JSX este permis doar în .tsx (și .jsx cu allowJs).
  • Să folosești "jsx": "react" cu React 17+ și să uiți import React from "react". Cu react-jsx, importul nu mai este necesar.

Comenzi înrudite

  • jsxImportSource: Pentru jsx: „react-jsx”, alege pachetul din care se importă automat funcțiile JSX (implicit react).
  • jsxFactory: Pentru jsx: „react”, alege funcția apelată pentru fiecare element (implicit React.createElement) și pentru fragmente.
  • moduleDetection: Decide când un fișier este modul (cu scope propriu) și când este script global; force face din fiecare fișier un modul.
  • target: Versiunea de JavaScript generată: sintaxa mai nouă decât ținta este transformată în cod echivalent mai vechi.