There’s always something going on in the world of JavaScript and TypeScript. The latest big news is the update of my favorite linter, ESLint, which got to version 9. If you already have some experience with it, you surely know that it no longer only provides static analysis of JavaScript. It can do much more.
We use ESLint on our projects as the main linter, which, in conjunction with Prettier, takes care of formatting and error detection in JavaScript, TypeScript, HTML and JSON. In combination with Stylelint, we also have SCSS under our control. Therefore, it isn’t surprising that we closely monitor the development of these tools and continuously deploy newer versions to maintain the consistency and quality of the code at the highest level.
So let’s take a look at what ESLint 9.0 has brought us.
New configuration format: Flat Config
The existing JSON format for ESLint configuration is no longer supported and will disappear completely in future versions. The new format is called Flat config, it’s written in JavaScript and its advantage is direct support of imports and more error-resistant configuration.
Fortunately, we didn’t have to manually rewrite the configurators when deploying the new version. There’s an official migrator that automatically converts the old config to the new format. However, in my experience, this tool solves only about 80% of the work. The rest requires manual intervention, especially if you’ve added your own modifications to the config.
Faster and more accurate API
While I haven’t had time to fully explore all the new API options in ESLint 9 yet, the initial changes show improvements in performance and accuracy. The biggest advantage is the acceleration of code analysis, which is also reflected in the fact that the new API goes through files more efficiently and completely ignores warnings when using –quiet, which speeds up work with large projects.
Stricter rules: TypeScript and Angular in focus
As soon as the main rules were fine-tuned, everyone began to adapt the plugins to this new format. As a result, a huge number of new types of rules and optimizations have been added. Especially when working with TypeScript and Angular, I was pleasantly surprised how well these innovations can detect problems and improve code quality.
New rules in practice: What’s changing?
- Removing obsolete rules: Rules that were no longer relevant to newer versions of ECMAScript have been removed, such as no-extra-semi or no-inner-declarations.
- Addition of new rules:
- no-constant-binary-expression: Prevents the use of constant expressions in binary operations.
- no-empty-static-block: A measure that prohibits empty static blocks in classes.
- no-unused-private-class-members: A rule that helps detect unused private class members in TypeScript.
Examples:
1.
Previously: No checking of empty static blocks, which could lead to unnecessary code.
class Test {
static {}
}
Now: ESLint 9.0 detects an empty static block as an error:
Error: no-empty-static-block - Empty static blocks aren't allowed.
2.
Previously: Binary expression is constant and therefore unnecessary:
let a = 3;
if (a === 3) {
Now: ESLint 9 will mark this as a bug and offer a fix to make the code more understandable:
Error: no-constant-binary-expression - The use of constant expressions in conditions isn't allowed.
Enhanced format support: Lint JSON, Markdown, and more
Until now, I’ve been used to using ESLint primarily for JavaScript and TypeScript, but the new version pushes the boundaries a bit further. Using official plugins, ESLint now supports other formats such as JSON, Markdown, or even YAML, allowing you to analyze and check consistency across a wider range of files.
How it works in practice:
- Markdown: With the eslint-plugin-markdown plugin, we can now lint code directly in Markdown files. For example, if we have JavaScript code in the documentation, ESLint can analyze it and point out errors.
- JSON: In projects where we work with configuration files in the JSON format (e.g. package.json), we can now use ESLint to check the consistency and validation of these files.
- YAML: YAML is often used in CI/CD configurations. Now we can lint these files just like code to avoid deployment errors.
The most annoying rule? @angular-eslint/prefer-standalone
Currently, the most annoying rule in my opinion is @angular-eslint/prefer-standalone, which sets the component on standalone when autofixing, but doesn’t perform the imports and other necessary steps for a successful migration. This means that I have to do part of the migration manually, which slows me down. However, this is necessary because from Angular 19, standalone will be turned on by default for all components, which means that in addition to new components, we’ll gradually remodel the existing ones to standalone: true. So sooner or later, we won’t be able to avoid this change.
Increase in errors: More work, but a better result as well
Performance? Much faster. Accuracy? Upgraded. But when it comes to errors, it’s a disaster. It’s very likely that after upgrading to ESLint 9, the number of errors and warnings will double. The new rules are much stricter, more extensive, and they also mark as flawed those things that the linter didn’t check before.
Nevertheless, we’ve set all ESLint, TS-ESLint, Angular ESLint, ngrx eslint and Prettier rules to the recommended values. As annoying as it was at times, it turned out to be very helpful. Ultimately, they helped us to thoroughly review the entire code and fix flaws that we might otherwise have missed.
Switching to ESLint 9 was a challenge, but the result is definitely worth the effort. New stricter rules and improvements significantly help maintain high code quality, which is definitely worthwhile in the long run. Therefore, instead of looking for a shortcut in the form of disabling rules, I recommend adapting the project to these changes and taking advantage of all the new features that ESLint 9 offers. As a reward, you’ll get cleaner and better quality code that will be much easier to manage in the future.