Настройка parserOptions.project

В контексте статического анализа TypeScript-кода ключевым механизмом становится подключение проекта компилятора TypeScript к процессу линтинга. В ESLint это реализуется через параметр parserOptions.project, который используется парсером @typescript-eslint/parser для включения type-aware правил.

ESLint в базовой конфигурации работает с синтаксическим деревом (AST), не имея доступа к типам. Подключение parserOptions.project меняет модель анализа: линтер начинает использовать TypeScript Program, что позволяет выполнять правила, зависящие от системы типов, импорта модулей и контекста компиляции.


Роль parserOptions.project в архитектуре анализа

Без указания project ESLint анализирует файлы в изоляции. В этом режиме доступны только синтаксические правила: форматирование, базовые проверки, потенциально опасные конструкции.

При включении:

parserOptions: {
  project: "./tsconfig.json"
}

инициализируется TypeScript Program, который:

  • объединяет файлы проекта согласно tsconfig.json
  • строит граф зависимостей модулей
  • выполняет типизацию
  • предоставляет API для type-aware ESLint правил

Это позволяет правилам анализировать не только структуру кода, но и его смысл.


Базовая конфигурация с TypeScript

Типичная настройка включает:

import tsParser from "@typescript-eslint/parser";

export default {
  parser: tsParser,
  parserOptions: {
    project: "./tsconfig.json",
    tsconfigRootDir: __dirname,
    sourceType: "module"
  }
};

Ключевые параметры:

  • project — путь к tsconfig.json или массив путей
  • tsconfigRootDir — базовая директория для резолва конфигурации
  • sourceType — режим модулей (module или script)

Механизм работы TypeScript Program

При активации project происходит:

  1. Чтение tsconfig.json
  2. Формирование списка файлов (include, exclude)
  3. Построение AST для каждого файла
  4. Создание единого Program
  5. Передача TypeChecker в ESLint правила

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

  • no-floating-promises
  • no-misused-promises
  • strict-boolean-expressions
  • анализ типов возвращаемых значений

Множественные проекты

В монорепозиториях часто используется несколько tsconfig:

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

Такой режим приводит к созданию нескольких Program’ов, что увеличивает нагрузку на память и время анализа.

Особенности:

  • каждый файл сопоставляется с ближайшим проектом
  • возможны конфликты пересекающихся include-путей
  • кеширование становится критически важным

Производительность и стоимость анализа

Использование parserOptions.project существенно влияет на производительность:

Без project:

  • быстрый парсинг AST
  • минимальная память
  • линтинг близок к синтаксическому

С project:

  • загрузка TypeScript Program
  • построение type graph
  • увеличение времени запуска ESLint в 2–10 раз
  • рост потребления памяти

Основная причина замедления — повторное создание TypeChecker и анализ зависимостей.


Кеширование TypeScript Program

В современных версиях @typescript-eslint/parser используется кеширование Program:

  • повторное использование AST
  • инкрементальная пересборка
  • хранение TypeChecker между запусками

Однако кеш эффективен только при стабильной структуре проекта.

Факторы, ухудшающие кеширование:

  • динамически изменяемые tsconfig
  • частые изменения include/exclude
  • нестабильные пути файлов

Типичные ошибки конфигурации

1. Неправильный tsconfigRootDir

parserOptions: {
  project: "./tsconfig.json",
  tsconfigRootDir: process.cwd()
}

Если ESLint запускается не из корня проекта, tsconfig может не находиться, что приводит к падению анализа.


2. Использование project без необходимости

Если в проекте нет type-aware правил, подключение project только замедляет процесс без пользы.


3. Конфликт include/exclude

{
  "include": ["src"],
  "exclude": ["node_modules"]
}

Если ESLint анализирует файлы вне include, TypeScript Program их не распознаёт.


4. Ошибка “You should not use parserOptions.project”

Возникает, когда:

  • файл не входит в tsconfig
  • ESLint анализирует временные или генерируемые файлы
  • используется flat config без корректного сопоставления проектов

Интеграция с flat config ESLint

В новой конфигурации ESLint (flat config) настройка сохраняется:

export default [
  {
    files: ["**/*.ts"],
    languageOptions: {
      parser: tsParser,
      parserOptions: {
        project: "./tsconfig.json"
      }
    }
  }
];

Особенность flat config:

  • более точное сопоставление файлов
  • явное указание scope анализа
  • меньше скрытых глобальных настроек

Несколько tsconfig и projectService

Современные версии @typescript-eslint поддерживают projectService:

  • автоматическое определение подходящего tsconfig
  • уменьшение необходимости ручного перечисления проектов
  • улучшение работы в монорепозиториях

Принцип:

  • файл сопоставляется с ближайшим tsconfig
  • создаётся кешированный Program
  • повторное использование TypeChecker

Производственные сценарии использования

Монорепозиторий

  • отдельный tsconfig на пакет
  • объединённый ESLint config
  • использование массива project

Приложение с одним tsconfig

  • один Program
  • минимальная сложность
  • максимальная стабильность кеша

Библиотека

  • строгий tsconfig.lib.json
  • включение деклараций (declaration: true)
  • обязательный type-aware анализ для API

Влияние на правила ESLint

Наличие parserOptions.project открывает доступ к правилам, которые:

  • анализируют реальные типы
  • проверяют корректность Promise-цепочек
  • выявляют небезопасные преобразования типов
  • проверяют соответствие API контрактам

Примеры категорий:

  • безопасность типов
  • корректность асинхронного кода
  • строгая работа с null/undefined
  • корректность React props (в связке с plugin)

Оптимизационные стратегии

Для снижения нагрузки применяются:

  • ограничение файлов через files в конфигурации
  • исключение тестов из type-aware анализа
  • разделение конфигов (base + type-aware)
  • использование отдельных запусков ESLint для разных частей проекта

Поведение при изменении кода

TypeScript Program пересобирается при:

  • изменении импортов
  • изменении структуры файлов
  • изменении tsconfig

ESLint старается минимизировать пересоздание, но при крупных изменениях пересчёт неизбежен.


Диагностика проблем

Типовые признаки неправильной настройки:

  • ошибки “file is not in project”
  • резкое падение производительности
  • несоответствие правил и реального поведения TypeScript
  • отсутствие type-aware проверок

Анализ обычно начинается с:

  • проверки tsconfig include
  • проверки tsconfigRootDir
  • проверки сопоставления файлов с проектами