Nomadic cattle rustler and inventor of the electric lasso.
Company Website
Follow me on twitter
Contact me for frontend answers.

from tslint to eslint.....all the things...eslintrc, webpack, cmd line and vscode

May 07, 2019

Why??

Long and the short of it is, tslint is on the way out which is really great as tslint has always felt like a very poor man’s eslint.

@typescript-eslint/no-explicit-any

I cannot believe I’ve missed this thing of great beauty. Too many typescript projects are typescript in file extension only. I’ve recently seen a lot of angular typescript code examples and open source projects littered with any, this would put a stop to this treasonous act.

How

Enough waffle, here is what I did on a react project.

npm packages

npm uninstall tslint -D

npm i eslint \
      babel-eslint \
      @typescript-eslint/parser \
      @typescript-eslint/eslint-plugin \
      eslint-plugin-react-hooks@next \
      eslint-plugin-react \
      eslint-plugin-prettier \
      eslint-loader -D

tslint.json becomes eslintrc.json

mv tslint.json eslintrc.json

Here is the guts of my migrated eslintrc.json file, I have omitted a lot of rules for brevity

{
  "parser": "@typescript-eslint/parser",
  "plugins": ["@typescript-eslint", "react-hooks", "prettier", "jsx-a11y"],
  "extends": [
    "plugin:@typescript-eslint/recommended",
    "plugin:react/recommended",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint",
    "plugin:jsx-a11y/recommended"
  ],
  "parserOptions": {
    "ecmaVersion": 2018,
    "sourceType": "module",
    "project": "./tsconfig.json"
  },
  "env": {
    "node": true,
    "commonjs": true,
    "es6": true,
    "jest": true
  },
  "rules": {
    "indent": "off",
    "@typescript-eslint/indent": "off",
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn",
    "react/prop-types": "off"
  },
  "settings": {
    "react": {
      "pragma": "React",
      "version": "detect"
    }
  }
}

Hopefully this is all self explanatory but some notes of interest are:

  • line 2 - specifies the @typescript-eslint/parser parser (talk about stating the obvious).
  • lines 2 to 9 - add whatever plugins and extend to your taste.
  • line 8 - provides a tsconfig.json to the parser.
  • line 24 - turn that nasty prop-types business off
  • line 29 - tell the parser to detect the react version, rather than explicity setting it.

I am extending plugin:@typescript-eslint/recommended which adds the delicious @typescript-eslint/no-explicit-any that I’ve been waiting for all my life…or at least all my typescript life.

webpack

Goodbye tslint-loader and hello eslint-loader, the new and shiny configuration looks like this:

{
  test: /\.tsx$/,
  enforce: 'pre',
  use: [
    {
      loader: 'eslint-loader',
      options: {
        fix: isProduction,
        emitWarning: isDevelopment,
        failOnWarning: isProduction,
        configFile: paths.esLintConfig
      }
    }
  ]
},

// const isDeveloment = process.env.NODE_ENV === 'development';
// const isProduction = process.env.NODE_ENV === 'production';

You can get a list of all the eslint-loader options on the repo’s README here.

Points of interest here are:

  • line 9 ensures we only emit warnings when in development mode so we don’t have to constantly restart the webpack dev server.
  • line 10 ensures even warnings will not ensure a successful build when building for production.
  • line 11 specifies the path to the eslintrc.json file. You might not need to do this but I was upgrading a monorepo and the loader bypassed my eslintrc.json for some reason so I had to explicitly set it.

calling eslint from the cmd line

I have my own @cutting/devtools package and I shell out to this file for typescript only builds.

I use node to create a process which equates to calling the eslint shebang script with the following arguments:

./node_modules/.bin/eslint ./src --ext .ts,.tsx --ignore-pattern *.test.* -c ./eslintrc.json --fix

vscode

I ripped out all my tslint settings.

In my global user settings.json I added the following:

"editor.formatOnSave": true,
  "eslint.enable": true,
  "eslint.autoFixOnSave": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    { "language": "typescript", "autoFix": true },
    { "language": "typescriptreact", "autoFix": true }
  ],
  "[javascript]": {
    "editor.formatOnSave": false
  },
  "[javascriptreact]": {
    "editor.formatOnSave": false
  },
  "[typescript]": {
    "editor.formatOnSave": false
  },
  "[typescriptreact]": {
    "editor.formatOnSave": false
  },
  "eslint.provideLintTask": true,
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }

In my monorepo project specific settings.json file, I added the following as I had the same issue with the eslintrc.json file not being found:

  "eslint.options": {
    "configFile": "../../eslintrc.json"
  }

Observe the output window

I might be stating the obvious here but keep an eye on the eslint output window while migrating:

debug window

Epilogue

This is a huge step forward, tslint has always been a poor man’s eslint but we have now reached parity.


Paul Cowan

Nomadic cattle rustler and inventor of the electric lasso.
Company Website
Follow me on twitter
Contact me for frontend answers.