ESLint в проектах на Angular

ESLint применяется как статический анализатор кода, обеспечивающий контроль качества JavaScript и TypeScript на этапе разработки. В Angular-экосистеме он заменил TSLint и стал стандартом де-факто для проверки корректности компонентов, сервисов, модулей и шаблонов.

Ключевая ценность ESLint в Angular заключается в объединении анализа TypeScript-кода и HTML-шаблонов компонентов в единую систему правил. Это позволяет выявлять ошибки структуры приложения, нарушения архитектурных соглашений и потенциальные проблемы производительности до запуска сборки.


Экосистема @angular-eslint

Интеграция ESLint с Angular реализуется через набор пакетов @angular-eslint. Он обеспечивает поддержку специфики фреймворка: декораторов, DI-контейнера, шаблонов и lifecycle hooks.

Основные пакеты:

  • @angular-eslint/eslint-plugin — набор правил для Angular-кода
  • @angular-eslint/eslint-plugin-template — анализ HTML-шаблонов
  • @angular-eslint/template-parser — парсер Angular templates
  • @angular-eslint/schematics — автоматическая миграция и настройка
  • @angular-eslint/builder — интеграция с Angular CLI

Эти компоненты формируют связку, позволяющую ESLint работать не только с TypeScript, но и с template-driven частью приложения.


Миграция с TSLint

Исторически Angular использовал TSLint, однако его развитие прекращено. Переход на ESLint выполняется через schematics:

ng add @angular-eslint/schematics

В процессе миграции:

  • удаляется tslint.json
  • добавляется .eslintrc.json или eslint.config.*
  • обновляются builder-конфигурации в angular.json
  • подключаются правила @angular-eslint

Автоматизация снижает количество ручных правок, но требует проверки совместимости кастомных правил, особенно в больших проектах.


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

Классическая конфигурация Angular-проекта строится на JSON-файле:

{
  "root": true,
  "overrides": [
    {
      "files": ["*.ts"],
      "extends": [
        "plugin:@angular-eslint/recommended",
        "plugin:@typescript-eslint/recommended"
      ],
      "parserOptions": {
        "project": ["tsconfig.json"]
      },
      "rules": {}
    },
    {
      "files": ["*.html"],
      "extends": [
        "plugin:@angular-eslint/template/recommended"
      ],
      "rules": {}
    }
  ]
}

Архитектура конфигурации основана на разделении контекстов:

  • TypeScript-код компонентов и сервисов
  • HTML-шаблоны Angular
  • тестовые файлы (опционально отдельный override)

Такой подход позволяет применять разные наборы правил к разным частям проекта.


Flat Config и современный формат ESLint

Современная версия ESLint поддерживает flat config (eslint.config.js), где исключается наследование через extends в пользу явной композиции:

import tseslint from "typescript-eslint";
import angular from "@angular-eslint/eslint-plugin";

export default [
  ...tseslint.configs.recommended,
  {
    files: ["**/*.ts"],
    plugins: {
      "@angular-eslint": angular
    },
    rules: {
      "@angular-eslint/directive-selector": "error"
    }
  }
];

Flat config уменьшает сложность цепочек наследования и упрощает анализ источника правил.


Проверка TypeScript-кода в Angular

Интеграция с TypeScript осуществляется через @typescript-eslint/parser и соответствующий plugin.

Ключевые аспекты:

  • использование parserOptions.project для анализа типов
  • контроль strict mode в tsconfig.json
  • проверка корректности DI-инъекций
  • анализ lifecycle hooks (например, корректное использование ngOnInit)

Типичные правила:

  • запрет неиспользуемых переменных
  • контроль явных типов
  • предотвращение unsafe any
  • проверка Promise/Observable handling

Особое значение имеет согласованность между ESLint и TypeScript compiler options, так как расхождение приводит к дублированию или пропуску ошибок.


Линтинг Angular-шаблонов

HTML-шаблоны в Angular представляют отдельную зону анализа. Для этого используется @angular-eslint/template-parser.

Шаблонный анализ включает:

  • проверку binding expressions
  • анализ структурных директив (*ngIf, *ngFor)
  • контроль доступности (a11y)
  • проверку валидности Angular pipes

Пример конфигурации:

{
  "files": ["*.html"],
  "extends": ["plugin:@angular-eslint/template/recommended"],
  "rules": {
    "@angular-eslint/template/no-negated-async": "error"
  }
}

Особое внимание уделяется выражениям внутри шаблонов, так как они выполняются в runtime и могут создавать скрытые ошибки.


Архитектурные правила Angular ESLint

Angular ESLint включает правила, направленные на соблюдение архитектурных соглашений:

  • именование компонентов и директив
  • структура селекторов
  • ограничения на импорты
  • контроль зависимости между слоями приложения

Пример правила:

  • @angular-eslint/component-selector
  • @angular-eslint/directive-selector

Они обеспечивают единообразие структуры проекта:

@Component({
  selector: 'app-user-card'
})

Нарушения naming convention выявляются до этапа сборки, предотвращая фрагментацию кодовой базы.


Контроль зависимостей и модульной структуры

В крупных Angular-приложениях важно контролировать зависимость между слоями:

  • feature modules
  • shared modules
  • core services

ESLint используется совместно с плагинами для архитектурных ограничений:

  • запрет импорта feature-модулей в shared
  • контроль циклических зависимостей
  • ограничение доступа к внутренним API

Дополнительно применяются правила import/no-cycle и boundaries.


Интеграция с Angular CLI

Angular CLI поддерживает ESLint через builder:

"lint": {
  "builder": "@angular-eslint/builder:lint",
  "options": {
    "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
  }
}

Запуск анализа:

ng lint

CLI обеспечивает унифицированный запуск анализа в рамках проекта, включая CI-сценарии.


Линтинг в CI/CD

ESLint часто интегрируется в pipeline:

  • GitHub Actions
  • GitLab CI
  • Jenkins

Типовой сценарий:

npm run lint

При наличии ошибок сборка блокируется. Это позволяет:

  • предотвращать попадание некорректного кода в main branch
  • стандартизировать стиль кода
  • фиксировать архитектурные нарушения

Pre-commit hooks

Для локального контроля используется Husky и lint-staged:

{
  "lint-staged": {
    "*.ts": "eslint --fix",
    "*.html": "eslint"
  }
}

Такой механизм снижает нагрузку на CI и переносит часть проверки на этап коммита.


Работа с монорепозиториями (Nx)

В экосистеме Nx ESLint используется как основной инструмент анализа границ модулей.

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

  • генерация конфигураций per-project
  • enforce-module-boundaries
  • caching lint results
  • distributed execution

Правило boundaries позволяет ограничивать импорт между библиотеками:

"@nx/enforce-module-boundaries": [
  "error",
  {
    "depConstraints": [
      {
        "sourceTag": "feature",
        "onlyDependOnLibsWithTags": ["shared", "core"]
      }
    ]
  }
]

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

При увеличении размера Angular-проекта ESLint может становиться узким местом. Основные факторы влияния:

  • использование type-aware linting
  • количество override-конфигураций
  • глубина анализа шаблонов
  • количество кастомных правил

Оптимизация включает:

  • отключение type-aware rules там, где они не критичны
  • разделение конфигураций по проектам
  • использование cache (--cache)
  • ограничение файловых паттернов

Кастомные правила ESLint

ESLint позволяет создавать собственные правила для Angular-проектов:

module.exports = {
  create(context) {
    return {
      "ClassDeclaration"(node) {
        if (!node.decorators) {
          context.report({
            node,
            message: "Component requires decorator"
          });
        }
      }
    };
  }
};

В Angular контексте такие правила используются для:

  • проверки архитектурных соглашений
  • контроля DI-паттернов
  • enforcement naming conventions beyond defaults

Безопасность и качество кода

ESLint в Angular применяется не только для стиля, но и для предотвращения runtime-ошибок:

  • использование безопасных выражений в шаблонах
  • контроль null/undefined
  • предотвращение unsafe DOM access
  • проверка async subscriptions

Особое значение имеет сочетание ESLint с strict TypeScript mode, что формирует многоуровневую систему защиты.


Расширение через плагины

Помимо @angular-eslint, используются дополнительные плагины:

  • eslint-plugin-import
  • eslint-plugin-rxjs
  • eslint-plugin-jsdoc
  • eslint-plugin-unicorn

В Angular проектах особенно важен rxjs-анализ:

  • контроль unsubscribe
  • предотвращение memory leaks
  • проверка операторов потоков

Поддержка больших команд

В корпоративных Angular-проектах ESLint становится инструментом стандартизации:

  • единые правила кодирования
  • автоматическое исправление (--fix)
  • унификация архитектуры
  • снижение code review overhead

Комбинация CLI, CI и pre-commit hooks формирует многоуровневую систему контроля качества кода.