Type-aware правила ESLint существенно изменяют модель выполнения линтинга в JavaScript/TypeScript-проектах, поскольку переходят от анализа синтаксического дерева к использованию полной типовой информации, предоставляемой компилятором TypeScript. Это расширяет возможности проверок, но вводит значительные издержки на этапе подготовки программы и выполнения правил.
При использовании @typescript-eslint/parser с параметром
parserOptions.project ESLint перестаёт работать только с
AST и подключает TypeScript Program. Этот режим позволяет правилам
обращаться к TypeChecker, извлекать реальные типы
выражений, анализировать дженерики, перегрузки функций и контекст вывода
типов.
parserOptions: {
project: ['./tsconfig.json']
}
В этот момент создаётся полноценная инфраструктура компилятора TypeScript:
tsconfigProgram и TypeCheckerИменно этот этап является основным источником затрат.
Создание Program — операция, линейно зависящая от
количества файлов, включённых в tsconfig. В крупных
монорепозиториях это может означать тысячи модулей, даже если ESLint
анализирует лишь небольшую часть.
Особенность заключается в том, что TypeScript не создаёт “частичный” program по умолчанию — он стремится собрать полное представление о проекте.
При использовании нескольких конфигураций:
tsconfig.app.jsontsconfig.test.jsontsconfig.node.jsonESLint вынужден создавать отдельный Program для каждого контекста файлов. Это приводит к повторной загрузке одних и тех же исходников и повторному построению графа зависимостей.
Type-aware правила, такие как:
@typescript-eslint/no-floating-promises@typescript-eslint/no-misused-promises@typescript-eslint/strict-boolean-expressionsиспользуют checker.getTypeAtLocation() или аналоги. Это
делает каждое обращение к типу потенциально дорогим, особенно при
глубокой цепочке типов или сложных union/intersection конструкциях.
Синтаксический режим ESLint ограничивается структурой AST:
Type-aware режим добавляет:
Разница в стоимости выполнения может быть кратной, особенно при включении строгих правил TypeScript ESLint.
В монорепозиториях с пакетной структурой основная проблема возникает из-за пересечения:
node_modulesindex.ts)Каждая такая конструкция увеличивает нагрузку на TypeChecker, так как расширяет область вывода типов.
Дополнительно влияет количество файлов, попадающих в
include tsconfig. Даже если ESLint запускается только на
src, TypeScript может подтянуть вспомогательные файлы через
зависимости.
Снижение стоимости type-aware проверки достигается уменьшением зоны действия TypeScript Program.
Ключевым фактором является строгое разделение конфигураций:
include{
"include": ["src/**/*.ts"],
"exclude": ["**/*.test.ts", "dist", "node_modules"]
}
Чем меньше файлов входит в Program, тем быстрее происходит инициализация и последующие запросы к TypeChecker.
ESLint поддерживает файловый кэш:
eslint . --cache
Кэширование уменьшает количество повторных вычислений AST и повторного запуска правил. Однако в type-aware режиме важно учитывать, что:
Таким образом, кэш эффективен преимущественно в инкрементальных сценариях CI и локальной разработки.
Практика разделения конфигураций ESLint позволяет минимизировать нагрузку:
В редакторе часто достаточно синтаксического анализа, поскольку скорость отклика важнее полноты проверки.
В CI, наоборот, допустим полный анализ с type-aware правилами, так как стоимость компенсируется единичным запуском.
Не все файлы требуют глубокого анализа типов. Наиболее дорогими являются:
Использование overrides позволяет точечно включать
типовые правила:
overrides: [
{
files: ['src/**/*.ts'],
parserOptions: {
project: ['./tsconfig.json']
}
}
]
Исключение вспомогательных областей снижает количество обращений к TypeChecker.
TypeScript Project References изменяет структуру Program, разбивая его на несколько связанных проектов. Это снижает нагрузку за счёт:
.tsbuildinfoОднако ESLint не всегда полностью использует преимущества инкрементальной сборки, поскольку создаёт собственную модель Program. Тем не менее разделение проектов уменьшает размер каждого отдельного графа зависимостей.
Некоторые конструкции TypeScript оказывают непропорциональное влияние на производительность:
При анализе таких конструкций TypeChecker может выполнять многократные вычисления, особенно при повторных вызовах правил.
Это напрямую влияет на правила ESLint, которые запрашивают тип несколько раз для одного узла AST.
Одной из ключевых оптимизаций является повторное использование
TypeScript Program между запусками ESLint. Современные версии
typescript-eslint стремятся к этому через internal caching,
однако:
Поэтому стабильная структура проекта важнее микрооптимизаций.
Совокупная стоимость type-aware анализа растёт нелинейно при увеличении количества правил. Причина заключается в том, что:
Поэтому набор правил влияет на производительность сильнее, чем кажется при линейной оценке.
Type-aware анализ обеспечивает более строгую проверку корректности кода, но требует контроля над инфраструктурой проекта. Основные факторы, влияющие на баланс:
Поведение ESLint в таком режиме становится ближе к поведению компилятора TypeScript, чем к классическому линтеру, и производительность начинает определяться характеристиками типовой системы проекта, а не только алгоритмами анализа AST.