Migrating from TSLint to ESLint on Gatsby

Image for post
Image for post
Photo by Nong Vang on Unsplash

In my previous blogs, I briefly touched upon the basics about setting up ESLint with TypeScript, but I’d like to show you a real world example of migrating from TSLint to ESLint on an existing project built on top of Gatsby.

The whole migration process is split into three parts:

  • Setting up ESLint
  • Adding up rules and test running
  • Cleaning TSLint

Let’s get started!

First, install ESLint and relevant packages:

 “eslint”: “7.9.0”,
“eslint-config-airbnb”: “18.2.0”,
“eslint-config-prettier”: “6.11.0”,
“eslint-loader”: “4.0.2”,
“eslint-plugin-import”: “2.22.0”,
“eslint-plugin-react”: “7.20.6”,

Since we are working with TypeScript we also need:

 “@typescript-eslint/eslint-plugin”: “4.0.0”,
@typescript-eslint/eslint-plugin-tslint”: “4.0.0”,
@typescript-eslint/parser”: “4.0.0”,

Finally, to get all these working with Gatsby we need to install Gatsby specific plugin (if you haven’t worked with Gatsby yet, thinking of it like extra webpack plugin you need):

“gatsby-plugin-eslint”: “2.0.8”,

Next, shall we do review each configuration and rule of the tslint file one by one? Of course not! I’m going to show you a magic. At the root of the project, run npx tslint-to-eslint-config .

This will take your TSLint configuration and create the “closest” ESLint configuration from it. (See more here)

There should now be a new .eslintrc.js file, a log file (tslint-to-eslint-config.log).

Essentially, the command keeps a mapping of rule converters, keyed by TSLint rule name. These converters take in the rule arguments for the TSLint rule and output the equivalent ESLint rule configuration:

Note that your auto-generated .eslintrc.js might be unnecessarily verbose(This is especially true if you are migrating an established project. If you apply it to a new project it might be less messier), so I’d rather to delete most of the rules in the .eslintrc.js , just keeping the important parts like extends, parser, plugins, etc.

Also, don’t forget to add an .eslintignore file and relevant paths below like:

public/
jest.config.js
static/
jest.setup.ts

Next step, go to gatsby-config.js and change the “gatsby-plugin-tslint”, to “gatsby-plugin-eslint” .

And finally change the package.json script:

 “lint”: “tslint — project .”,
“lint”: “eslint .”,

This is the most difficult part, since we remove auto-generated rules in .eslintrc.js , we have to add relevant rules back by

  • referencing to existing rules in other repositories (if they are under same organisation then it’s common that they share the same sets of rules) and,
  • clearing up the alerts using eslint . , since there will always be some project specific rules

Adding the first part is easy. You just need to reference any project .eslintrc.js and copy the relevant rules over. The second part, depends how old and complex your project is, can be quite difficult. For me, I ended up with 400+ alerts the first time I run eslint .

While complaining won’t make it better, you should take it as an opportunity that the project exposes some hidden problems that the previous TSlint might not be able to detect.

Luckily, after adding the following rules, there are just about 30ish exceptions left.

"rules": {
"max-len": [1, {"code": 150 }],
"quotes": [2, "double", { "avoidEscape": true }],
"import/extensions": [
"error",
"ignorePackages",
{
"js": "never",
"jsx": "never",
"ts": "never",
"tsx": "never"
}
],
"react/prop-types": 0,
"react/jsx-props-no-spreading": 0,
"import/prefer-default-export": 0,
"import/no-named-default": 0,
"react/jsx-filename-extension": 0,
"implicit-arrow-linebreak": 0,
"react/no-unescaped-entities": 0,
"react/require-default-props": 0,
"no-nested-ternary": 0,
"no-shadow": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/no-explicit-any": 0,
"no-use-before-define": 0,
"react/no-unused-prop-types": 0,
"@typescript-eslint/ban-ts-comment": 0,
"react/no-array-index-key": 0,
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": ["**/*.stories.tsx", "**/*.spec.tsx", "**/*.spec.ts"]
}
]
}

The rest 30ish rules are mostly file/line specific. In this case, you might want to add eslint ignore .

After clearing up the eslint . warnings, you would need to test with other scripts like npm start & npm run build . In my case, I found that I need to add a separate tsconfig file for eslint only and keep the original tsconfig for running and building the project.

Congratulations! You’ve gone this far, now it’s the final step to clean up TSLint.

In my case, I need to uninstall following packages:

 “tslint”: “⁵.20.0”,
“tslint-loader”: “³.5.4”,
“tslint-react”: “⁴.1.0”,

I also need to remove the tslint.json file as well as the dependency on tslint in the package.json file.

That’s so much of it! Happy reading!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store