Avatar ·

Ошибка ESLint: Cannot read file '.../tsconfig.json' — как исправить?

Привет! Я новичок в TypeScript и пытаюсь настроить линтинг в своём проекте. Установил ESLint, typescript-eslint, создал конфиг `.eslintrc.json`. Но когда запускаю ESLint, получаю ошибку: ``` Parsing error: Cannot read file '.../tsconfig.json'.eslint ``` Вот мой файл `.eslintrc.json`: ```json { "parser": "@typescript-eslint/parser", "parserOptions": { "project": "./tsconfig.json" }, "plugins": ["@typescript-eslint"], "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended" ] } ``` И мой `tsconfig.json` лежит в корне проекта: ```json { "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "outDir": "./dist" }, "include": ["src/**/*"] } ``` Структура папок: ``` my-project/ ├── .eslintrc.json ├── tsconfig.json ├── src/ │ └── index.ts └── package.json ``` Я проверил, что файл `tsconfig.json` существует и находится в корне. Что я делаю не так? Почему ESLint не может его прочитать? Пробовал указывать абсолютный путь — тоже не работает. Подскажите, пожалуйста, как это исправить. <<>>

Причина ошибки

Ошибка возникает из-за того, что ESLint запускается не из корня проекта, а из другой директории (например, из подпапки src или через редактор кода, который может запускать ESLint с неправильным рабочим каталогом). Парсер @typescript-eslint/parser ищет tsconfig.json относительно текущей рабочей директории, а не относительно файла конфигурации ESLint.

Решение 1: Использовать абсолютный путь (не рекомендуется)

Можно указать полный путь к tsconfig.json:

{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "/home/user/my-project/tsconfig.json"
  }
}

Но это плохое решение — при переносе проекта на другой компьютер или в другую папку путь сломается.

Решение 2: Установить корневой каталог через ESLint (рекомендуется)

Лучший способ — использовать опцию tsconfigRootDir в parserOptions. Она указывает парсеру, откуда искать tsconfig.json:

{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "./tsconfig.json",
    "tsconfigRootDir": "./"
  }
}

Проблема: tsconfigRootDir тоже может интерпретироваться относительно текущей директории. Надёжнее использовать __dirname в конфигурации ESLint, если вы используете .eslintrc.js вместо JSON:

// .eslintrc.js
const path = require('path');

module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: path.resolve(__dirname, 'tsconfig.json'),
    tsconfigRootDir: __dirname,
  },
  plugins: ['@typescript-eslint'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
  ],
};

Решение 3: Использовать глобальный конфиг (для монорепозиториев)

Если у вас монорепозиторий или проект с несколькими tsconfig.json, укажите массив путей:

{
  "parserOptions": {
    "project": ["./tsconfig.json", "./packages/*/tsconfig.json"]
  }
}

Решение 4: Проверить, как запускается ESLint

  • Убедитесь, что вы запускаете ESLint из корня проекта: cd my-project && npx eslint src/
  • В VS Code проверьте настройки: eslint.workingDirectories — укажите массив с путём к корню проекта
  • В WebStorm: File → Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint → Working directories

Решение 5: Убедиться, что tsconfig.json валидный

Иногда ошибка возникает из-за невалидного JSON. Проверьте:

npx tsc --showConfig

Эта команда покажет, как TypeScript видит ваш конфиг. Если ошибок нет — проблема в путях ESLint.

Важно!

Опция project в parserOptions заставляет ESLint загружать TypeScript проект. Это нужно для правил, которые требуют типовой информации (например, @typescript-eslint/no-floating-promises). Если вам не нужны правила, использующие типы, можно просто убрать опцию project — тогда ESLint будет работать быстрее и без этой ошибки:

{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": false
  }
}

Но тогда вы потеряете часть правил, которые требуют типов.

Итог

Самое надёжное решение — перейти на .eslintrc.js и использовать path.resolve(__dirname, 'tsconfig.json'). Это гарантирует, что путь будет правильным независимо от того, откуда запущен ESLint.

<<>>

Альтернативный подход: Использовать ESLint Flat Config

В последних версиях ESLint (v9+) рекомендуется использовать новый формат конфигурации — eslint.config.js (flat config). Он решает проблему с путями более элегантно:

// eslint.config.js
import tseslint from 'typescript-eslint';

export default tseslint.config(
  {
    files: ['**/*.ts'],
    extends: [
      ...tseslint.configs.recommended,
    ],
    languageOptions: {
      parserOptions: {
        project: true, // Автоматически найдёт tsconfig.json
        tsconfigRootDir: import.meta.dirname,
      },
    },
  }
);

В flat config опция project: true автоматически ищет tsconfig.json в корне проекта, а import.meta.dirname даёт правильный путь к текущей папке. Это избавляет от необходимости вручную указывать пути.

Если у вас старый проект

Можно временно отключить правила, требующие проект, и использовать только базовые правила TypeScript:

{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": false
  },
  "plugins": ["@typescript-eslint"],
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "rules": {
    "@typescript-eslint/no-floating-promises": "off",
    "@typescript-eslint/no-misused-promises": "off"
  }
}

Это не идеальное решение, но оно позволяет быстро начать работу, не разбираясь с настройкой путей.