Eslint had a major update which caused a lot of problems with the existing configuration I had in different projects. This led me to postpone the migration until things settled down a bit. Hoping that others had time to find fixes, workaround or examples to follow.
And it worked since the migration guide got created and is now better than ever. In this article I’ll show how I updated my old config to the new one so it works with typescript.
Eslint v8 Previous config
We talked already about configuring typescript which mentions how to set up eslint (v8) with typescript. As well as how to create your own eslint configuration with custom rules.
Here is an old (now deprecated) .eslintrc.json
configuration file for eslint with the basics for jest and typescript:
{
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"jest"
],
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"env": {
"es6": true,
"node": true,
"jest": true
},
"extends": ["plugin:jest/recommended"],
"rules": {}
}
In this configuration we have:
- the
parser
andparserOptions
to use the typescript parser. - the
plugins
to load the typescript and jest plugins, - the
extends
to use the jest recommended rules (imported from the plugin). - the
rules
for additional custom eslint rules.
Now let’s see how this looks with eslint v9.
Eslint v9 New config
Migrated config
With the newer eslint version, the configuration file format has changed.
I am using the cjs (commonjs) format for the configuration file as eslint.config.cjs
.
It is similar to the .eslintrc.js
which I used before.
But all in all, the config as js, mjs, ts
are all pretty similar.
With v9 eslint uses a flat config system which is a single array of configuration objects.
The same configuration as above can now be written as:
// eslint.config.cjs
const typescript = require('@typescript-eslint/eslint-plugin');
const typescriptParser = require('@typescript-eslint/parser');
const jest = require('eslint-plugin-jest');
module.exports = [
{
ignores: ['dist/**', 'node_modules/**', 'coverage/**'],
},
{
files: ['**/*.ts'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
},
},
plugins: {
'@typescript-eslint': typescript,
'jest': jest,
},
rules: {
...typescript.configs.recommended.rules,
...jest.configs.recommended.rules,
},
},
];
If you were familiar with the deprecated overrides feature, then this new format will be similar. The configuration can be specified for different file groups, and the rules can be extended from the plugin’s recommended rules.
Here we have two elements in the configuration:
- the first one
- It only has
ignores
for the generic files to ignore with eslint.
- It only has
- the second one
- the
files
for the typescript files and within the associated plugins and rules.- the
plugins
to load the typescript and jest plugins, - the
rules
to extend from the recommended rules of the plugins and add custom rules.
- the
- We could set another
ignores
to ignore specific files matched by the glob pattern.
- the
No need to extend any more, just use the rules
for the plugin rules and your own on the selected files.
With React
Let’s say we have some React components in the project.
That means we have some tsx
files and eslint react plugin we’d like to include in our configuration.
Let’s update the configuration to include the React plugin and the recommended rules:
// eslint.config.cjs
// ...previous imports
const reactPlugin = require('eslint-plugin-react');
module.exports = [
// ...previous config from above
{
files: ['**/*.ts', '**/*.tsx'], // add tsx files for common typescript rules
// ...previous config from above
},
{
files: ['**/*.tsx'], // create a new config for tsx files only
ignores: ['build', 'public/build'],
plugins: {
'react': reactPlugin,
},
settings: {
react: {
version: 'detect',
},
},
rules: {
'no-trailing-spaces': 'error',
'no-irregular-whitespace': 'error',
'no-multiple-empty-lines': ['error', { 'max': 1, 'maxEOF': 1, 'maxBOF': 0 }],
...reactPlugin.configs.recommended.rules,
'react/jsx-tag-spacing': ['error', { 'beforeSelfClosing': 'always' }],
},
}
]
In this configuration we use the React plugin and extend it with some custom rules that can be both:
- default Eslint rules like
no trailing spaces
orno irregular whitespace
- plugin rules like
react/jsx-tag-spacing
which is a rule from the React plugin.
We also updated the previous file configuration to include tsx
files as well, so the typescript rules apply to them.
This simplifies and encapsulate the configuration for the different file types.