Плагин @typescript-eslint/eslint-plugin

Пакет @typescript-eslint/eslint-plugin представляет собой набор правил ESLint, разработанных специально для анализа кода на TypeScript. Его роль заключается в расширении стандартного набора ESLint-правил возможностями, учитывающими типы, синтаксис и особенности системы типов TypeScript.

ESLint по своей природе работает с ESTree-совместимым AST, однако TypeScript вводит собственные синтаксические конструкции (интерфейсы, перечисления, модификаторы доступа, generics, union/intersection типы), которые требуют отдельного разбора и специализированной логики анализа. Плагин выступает связующим звеном между ESLint и TypeScript-компилятором через использование @typescript-eslint/parser.


Установка и базовая конфигурация

Корректная работа плагина требует установки нескольких взаимосвязанных пакетов:

  • eslint
  • typescript
  • @typescript-eslint/parser
  • @typescript-eslint/eslint-plugin

Типичная установка в проекте:

npm install -D eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin

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

module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 2022,
    sourceType: 'module',
    project: './tsconfig.json',
  },
  plugins: ['@typescript-eslint'],
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
  ],
};

Ключевой момент — параметр project. Его наличие включает type-aware linting, при котором правила получают доступ к информации TypeScript Compiler API. Это существенно расширяет возможности анализа, но увеличивает время проверки.


Взаимодействие с @typescript-eslint/parser

Плагин не функционирует автономно. Он зависит от парсера @typescript-eslint/parser, который преобразует TypeScript-код в AST, совместимый с ESLint.

Основные задачи парсера:

  • преобразование TS-специфичного синтаксиса в расширенный ESTree
  • сохранение информации о типах (при включённом project)
  • предоставление доступа к TypeScript TypeChecker
  • нормализация AST для корректной работы правил

Без корректного парсера правила плагина либо не работают, либо работают в ограниченном режиме.


Архитектура правил @typescript-eslint/eslint-plugin

Плагин содержит набор правил, разделённых по категориям:

  • базовые корректирующие (error prevention)
  • типобезопасные (type-aware)
  • стилистические
  • правила миграции с ESLint core
  • правила производительности и архитектуры

Каждое правило реализовано как модуль, использующий ESLint Rule API, но дополненный доступом к TypeScript TypeChecker.


Категории правил

Корректность и предотвращение ошибок

Эти правила направлены на выявление потенциальных багов:

  • no-floating-promises
  • no-misused-promises
  • no-unsafe-assignment
  • no-unsafe-member-access
  • no-unsafe-call

Особенность этих правил заключается в использовании анализа типов. Например, no-floating-promises отслеживает промисы, которые не обрабатываются через await или .catch.


Type-aware правила

Данный класс правил требует включённого parserOptions.project.

Пример:

  • await-thenable
  • restrict-template-expressions
  • no-unnecessary-type-assertion
  • strict-boolean-expressions

Принцип работы основан на взаимодействии с TypeScript TypeChecker:

  • извлечение типа выражения
  • проверка совместимости типов
  • анализ narrowing (сужения типов)
  • контроль union-типа в логических выражениях

Стилистические правила

Часть правил заменяет или дополняет ESLint core:

  • no-extra-parens (TypeScript-aware версия)
  • consistent-type-imports
  • explicit-function-return-type
  • member-delimiter-style

Эти правила часто используются для унификации кодовой базы и повышения читаемости TypeScript-кода.


Правила замены ESLint core

Некоторые стандартные правила ESLint конфликтуют с TypeScript или не понимают его синтаксис. Плагин предоставляет аналоги:

ESLint core TypeScript ESLint
no-shadow @typescript-eslint/no-shadow
no-unused-vars @typescript-eslint/no-unused-vars
no-use-before-define @typescript-eslint/no-use-before-define

Замена обусловлена тем, что TypeScript вводит дополнительные сущности (типы, интерфейсы), которые ESLint core не учитывает.


Type-aware linting и влияние tsconfig

Включение parserOptions.project переводит ESLint в режим, при котором он анализирует проект через TypeScript Program API.

parserOptions: {
  project: './tsconfig.json',
}

Это приводит к следующим эффектам:

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

Особенно важно наличие корректного tsconfig.json, так как ошибки конфигурации могут приводить к деградации производительности или некорректным результатам.


Плагин предоставляет готовые наборы конфигураций.

extends: [
  'plugin:@typescript-eslint/recommended'
]

Включает базовый набор правил, предотвращающих очевидные ошибки и обеспечивающих совместимость с TypeScript.


strict

extends: [
  'plugin:@typescript-eslint/recommended-type-checked',
  'plugin:@typescript-eslint/strict'
]

Активирует более строгий режим анализа, включающий:

  • глубокий type-checking
  • строгие ограничения на unsafe операции
  • усиленный контроль типов

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

Type-aware правила значительно увеличивают нагрузку на систему.

Факторы влияния:

  • размер проекта
  • количество файлов в tsconfig
  • глубина типов
  • использование monorepo

Типичные методы оптимизации:

  • разделение tsconfig на несколько проектов
  • исключение тестовых файлов из type-aware linting
  • использование parserOptions.projectService (в новых версиях)
  • ограничение набора type-aware правил

Распространённые правила и их поведение

no-unused-vars (TypeScript версия)

Отслеживает неиспользуемые переменные с учётом типов и импортов.

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

  • игнорирует типовые импорты при необходимости
  • учитывает generics и type-only imports
  • корректно работает с enum и namespace

consistent-type-imports

Формирует единый стиль импорта типов:

import type { User } from './types';

Цель — разгрузка runtime-кода и улучшение tree-shaking.


no-misused-promises

Выявляет ситуации, где Promise используется как boolean или напрямую передаётся в синхронный контекст:

if (getData()) { }

Правильная форма требует явного await или обработки результата.


Интеграция с монорепозиториями

В монорепозиториях с несколькими tsconfig.json требуется отдельная настройка:

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

Проблематика:

  • увеличение времени анализа
  • возможные конфликты типов между пакетами
  • необходимость разделения ESLint cache

Часто применяется стратегия изолированных проектов с отдельными ESLint конфигурациями.


Совместимость с ESLint flat config

В новых версиях ESLint используется flat config:

export default [
  {
    languageOptions: {
      parser: tsParser,
    },
    plugins: {
      '@typescript-eslint': tsPlugin,
    },
  }
];

Плагин поддерживает flat config, однако некоторые legacy-конфигурации требуют адаптации правил и extends.


Ошибки конфигурации и их природа

Типичные проблемы:

Отсутствие project

Приводит к отключению type-aware правил или ошибке:

  • невозможность создания TypeScript Program
  • fallback в non-type-aware режим

Несоответствие tsconfig

Если ESLint запускается вне контекста TypeScript проекта:

  • отсутствуют типы
  • неверные пути
  • ошибки резолвинга модулей

Конфликт parserOptions

Использование одновременно babel-eslint и @typescript-eslint/parser приводит к некорректной работе AST.


Правила миграции с JavaScript в TypeScript

Плагин включает правила, упрощающие переход:

  • запрет JS-стиля var
  • контроль implicit any
  • требование явных типов в критичных местах

Пример:

function add(a, b) {
  return a + b;
}

При строгой конфигурации требуется:

function add(a: number, b: number): number {
  return a + b;
}

Роль плагина в архитектуре качества кода

@typescript-eslint/eslint-plugin выполняет функцию статического слоя контроля поверх TypeScript-компилятора.

TypeScript обеспечивает:

  • проверку типов
  • компиляцию

ESLint с плагином обеспечивает:

  • архитектурные ограничения
  • стиль кода
  • обнаружение анти-паттернов
  • контроль небезопасных операций

Разделение ответственности позволяет строить многоуровневую систему качества кода, где компилятор и линтер решают разные задачи, но работают совместно через единый AST и type system.