Ошибка "Cannot use JSX unless the '--jsx' flag is provided" в TypeScript и React
Hello, {name}!
; }; export default Greeting; ``` Когда я запускаю компиляцию через `tsc`, получаю ошибку: ``` Cannot use JSX unless the '--jsx' flag is provided. ``` Я использую TypeScript версии 5.0.3, React 18, и мой tsconfig.json выглядит так: ```json { "compilerOptions": { "target": "ES2020", "module": "ESNext", "strict": true, "esModuleInterop": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"] } ``` Я пробовал гуглить, но советы в интернете разнятся: кто-то говорит установить `"jsx": "react"`, кто-то — `"jsx": "preserve"`, а кто-то предлагает добавить `"jsxImportSource": "react"`. Я не понимаю, какой вариант правильный для моего случая. Также неясно, нужно ли мне дополнительно устанавливать какие-то пакеты, кроме `react` и `react-dom`. Помогите разобраться, пожалуйста! <<Причина ошибки
Ошибка возникает, потому что TypeScript по умолчанию не знает, как обрабатывать JSX-синтаксис (HTML-подобные теги внутри JavaScript/TypeScript). Для этого нужно явно указать компилятору, какой режим JSX использовать. В вашем tsconfig.json отсутствует параметр jsx.
Решение
Добавьте в compilerOptions вашего tsconfig.json следующую строку:
{
"compilerOptions": {
"jsx": "react-jsx", // или "react" — см. пояснение ниже
// остальные настройки...
}
}
Какой именно режим выбрать?
В современных проектах с React 17+ и TypeScript 4.1+ рекомендуется использовать "jsx": "react-jsx". Вот полная таблица режимов:
"react"— классический режим. Компилирует JSX в вызовыReact.createElement. Требует, чтобы React был в области видимости (нуженimport React from 'react'в каждом файле)."react-jsx"— новый режим (React 17+). Использует автоматический импорт изreact/jsx-runtime. Позволяет не писатьimport React from 'react'в каждом файле (но импорт для хуков и других функций всё равно нужен)."preserve"— оставляет JSX как есть. Используется, если дальнейшую обработку делает другой инструмент (например, Babel)."react-native"— для React Native.
Обновлённый tsconfig.json
Для вашего случая (React 18, TypeScript 5) оптимальный конфиг будет таким:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true,
"esModuleInterop": true,
"jsx": "react-jsx", // ✅ добавили эту строку
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"]
}
После этого ваш компонент можно упростить, убрав ненужный импорт React (хотя он не помешает):
// import React from 'react'; // можно удалить, если используете react-jsx
interface Props {
name: string;
}
const Greeting: React.FC<Props> = ({ name }) => {
return <h1>Hello, {name}!</h1>;
};
export default Greeting;
Дополнительные проверки
- Версии пакетов: убедитесь, что у вас установлены актуальные версии
@types/reactи@types/react-dom:
npm install --save-dev @types/react @types/react-dom
- Перезапустите компиляцию: после изменения
tsconfig.jsonвыполните:
npx tsc --noEmit # проверить без генерации файлов
npx tsc # скомпилировать
- IDE: если используете VSCode, перезагрузите окно (Ctrl+Shift+P → "Reload Window"), чтобы TypeScript Language Service подхватил новые настройки.
Почему это работает?
Параметр jsx в tsconfig.json сообщает компилятору TypeScript, как трансформировать JSX-синтаксис. Без него компилятор видит <h1> и не понимает, что это — это не валидный TypeScript, и не JSX, поэтому выдаёт ошибку. Указав "react-jsx", вы говорите: "используй новый автоматический режим React для преобразования JSX".
Альтернативный подход: использовать Babel для обработки JSX
Если вы не хотите, чтобы TypeScript обрабатывал JSX (например, вы используете Babel для других преобразований), можно установить режим "jsx": "preserve" и передать обработку JSX Babel'у.
Шаги:
- В
tsconfig.jsonукажите:{ "compilerOptions": { "jsx": "preserve", // остальные настройки... } } - Установите необходимые Babel-пакеты:
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript - Создайте файл
babel.config.json:{ "presets": [ "@babel/preset-env", ["@babel/preset-react", { "runtime": "automatic" }], "@babel/preset-typescript" ] } - Настройте сборку: TypeScript будет только проверять типы (
tsc --noEmit), а Babel — компилировать в JS.
Плюсы: больше гибкости, можно использовать экспериментальные фичи.
Минусы: сложнее настройка, два инструмента вместо одного.
Для простых проектов с React 18+ рекомендую первый вариант (только TypeScript с "jsx": "react-jsx") — это проще и быстрее.