Avatar ·

Ошибка "Cannot use JSX unless the '--jsx' flag is provided" в TypeScript и React

Всем привет! Я новичок в TypeScript и React, пытаюсь настроить проект, но столкнулся с ошибкой, которую не могу победить уже второй день. У меня есть простой компонент на React, который я пишу в файле с расширением .tsx: ```tsx import React from 'react'; interface Props { name: string; } const Greeting: React.FC = ({ name }) => { return

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;

Дополнительные проверки

  1. Версии пакетов: убедитесь, что у вас установлены актуальные версии @types/react и @types/react-dom:
npm install --save-dev @types/react @types/react-dom
  1. Перезапустите компиляцию: после изменения tsconfig.json выполните:
npx tsc --noEmit   # проверить без генерации файлов
npx tsc            # скомпилировать
  1. 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'у.

Шаги:

  1. В tsconfig.json укажите:
    {
      "compilerOptions": {
        "jsx": "preserve",
        // остальные настройки...
      }
    }
  2. Установите необходимые Babel-пакеты:
    npm install --save-dev @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
  3. Создайте файл babel.config.json:
    {
      "presets": [
        "@babel/preset-env",
        ["@babel/preset-react", { "runtime": "automatic" }],
        "@babel/preset-typescript"
      ]
    }
  4. Настройте сборку: TypeScript будет только проверять типы (tsc --noEmit), а Babel — компилировать в JS.

Плюсы: больше гибкости, можно использовать экспериментальные фичи.

Минусы: сложнее настройка, два инструмента вместо одного.

Для простых проектов с React 18+ рекомендую первый вариант (только TypeScript с "jsx": "react-jsx") — это проще и быстрее.