Back

Five ESLint Plugins That Improve Code Quality

Five ESLint Plugins That Improve Code Quality

You’ve configured ESLint. It catches unused variables and flags missing semicolons. But your codebase still accumulates subtle bugs, inconsistent imports, and accessibility issues that slip through code review. The default rules aren’t enough.

ESLint 9 introduced flat config (eslint.config.js), replacing the legacy .eslintrc format. This shift simplifies plugin integration and makes configuration more predictable. Whether you’ve migrated or still use the older format, the right plugins transform ESLint from a basic checker into a genuine quality gate.

Here are five plugins that address real problems in modern frontend projects—without bloating your tooling.

Key Takeaways

  • typescript-eslint enables type-aware linting that catches unsafe access patterns and forgotten await statements
  • eslint-plugin-import enforces module hygiene by validating paths, detecting circular dependencies, and organizing imports consistently
  • eslint-plugin-unicorn provides over 100 rules that push toward modern JavaScript patterns and prevent subtle bugs
  • eslint-plugin-jsx-a11y catches common accessibility issues in JSX before they reach users
  • @eslint/css extends linting beyond JavaScript to catch stylesheet errors under a unified workflow

typescript-eslint: Type-Aware Linting for TypeScript Projects

The @typescript-eslint plugin brings TypeScript’s type system into your linting workflow. Unlike basic syntax checks, type-aware rules catch issues that require understanding your code’s types.

Consider a function that might return null. Type-aware linting flags unsafe access patterns that runtime errors would otherwise reveal in production. Rules like no-floating-promises catch forgotten await statements, and no-unnecessary-condition identifies dead code branches.

For larger codebases, typescript-eslint offers Project Service, which improves performance by reusing TypeScript’s program instances across files. This matters when linting thousands of files in CI.

In flat config, you import the plugin directly and spread its recommended configurations. The setup integrates cleanly with ESLint 9’s flat-config model when using the standard typescript-eslint toolchain.

eslint-plugin-import: Module Hygiene and Import Organization

eslint-plugin-import prevents the chaos that accumulates in import statements across a growing codebase.

The plugin catches misspelled paths before runtime, ensures named imports match actual exports, and flags circular dependencies that cause subtle bugs. Its no-extraneous-dependencies rule prevents importing packages not listed in package.json—a common source of deployment failures.

The import/order rule enforces consistent grouping: external packages first, then internal modules, then relative imports. This consistency makes files scannable and diffs cleaner during code review.

For teams, this plugin eliminates style debates about import organization. Configure it once, and auto-fix handles the rest.

eslint-plugin-unicorn: Opinionated Bug Prevention

eslint-plugin-unicorn provides over 100 rules that catch subtle issues and enforce modern JavaScript patterns.

It flags Array.forEach when for...of would be clearer. It catches new Array(5) when you meant Array.from({ length: 5 }). It prevents process.exit() calls that skip cleanup handlers.

The plugin pushes toward modern syntax: preferring Array.includes() over indexOf() !== -1, suggesting String.replaceAll() over regex with global flags, and flagging outdated Number methods.

Not every rule fits every team. Start with the recommended preset, then disable rules that conflict with your codebase’s conventions.

eslint-plugin-jsx-a11y: JSX Accessibility Linting

eslint-plugin-jsx-a11y catches accessibility issues in JSX before they reach users.

The plugin flags images without alt attributes, buttons without accessible names, and form inputs missing labels. It catches autoFocus usage that disrupts keyboard navigation and identifies click handlers on non-interactive elements.

These rules don’t guarantee WCAG compliance—automated tools catch roughly 30% of accessibility issues. But they prevent the most common mistakes and build accessibility awareness into daily development.

For teams shipping user-facing applications, this plugin is essential. Accessibility bugs affect real users and carry legal implications in many jurisdictions.

@eslint/css: Linting Beyond JavaScript

ESLint now extends beyond JavaScript. The @eslint/css plugin brings static analysis to stylesheets, catching syntax errors and enforcing conventions.

Similarly, html-eslint validates HTML structure, flagging duplicate IDs, missing lang attributes, and invalid nesting.

These plugins matter for projects with CSS modules, HTML templates, or component libraries where markup quality affects rendering. They unify your linting workflow under a single tool rather than requiring separate validators.

Separation of Concerns: Linting vs. Formatting

One clarification: ESLint handles code quality, not formatting. Let Prettier manage semicolons, quotes, and indentation. Use eslint-config-prettier to disable ESLint rules that conflict with Prettier, then run both tools separately.

This separation keeps your ESLint configuration focused on catching bugs rather than enforcing style preferences.

Conclusion

These five plugins address distinct problems: type safety, import hygiene, modern patterns, accessibility, and cross-language linting. Add them incrementally. Enable recommended presets first, then customize rules as your team identifies friction points.

The goal isn’t maximum strictness—it’s catching real bugs before they ship.

FAQs

ESLint 9's flat config uses JavaScript modules instead of JSON or YAML. Export an array of configuration objects from eslint.config.js. Each object can specify files to target, plugins to use, and rules to apply. The ESLint documentation provides a migration guide, and most plugins now include flat config examples in their documentation.

Yes. These plugins target different concerns and rarely overlap. typescript-eslint handles type checking, eslint-plugin-import manages modules, unicorn enforces patterns, jsx-a11y covers accessibility, and @eslint/css handles stylesheets. If rule conflicts occur, disable the less specific rule in your configuration.

Type-aware rules from typescript-eslint add overhead because they require TypeScript's compiler. For large projects, enable Project Service to improve performance. Other plugins add minimal overhead. Run ESLint with the --cache flag to skip unchanged files and speed up repeated runs.

No. Start with each plugin's recommended preset, which includes battle-tested rules. Monitor your team's experience and disable rules that create friction without catching real bugs. The goal is practical bug prevention, not maximum strictness.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay