The horse is dead - cry: transition from tslint to eslint

Until recently, in all projects of the front, the developers of Dodo Pizza Engineering used tslint - a useful tool that tells you when you messed up the code, made inaccuracies, helps maintain the code in one style and corrects many comments. But then tslint took and died. Under the cut, I’ll tell you why it happened, how to stop pouring tears over the deceased and switch to the eslint tool, and also show something very intimate.







In fact, it all started a long time ago: the last release of the tslint kernel was already in 2016. And this is the moment when it is time to start saying “last,” if someone still says “last,” because that release was really the last. On February 19, 2019, an official post was released to stop the development of tslint. In it, the development company (by the way, it’s not even Microsoft) strongly advises everyone to switch to eslint, since their efforts will now be aimed at improving TypeScript support in this linter.



One language, one stack, one community



Microsoft sees TypeScript as the main web development language, which should supplant Java / ECMA Script. Obviously, such an ambitious goal implies a single stack of tools for the entire front-end development. This should greatly simplify the migration of the large JS community to TypeScript. In addition to the guarantee of trust from Microsoft, eslint has a better architecture than tslint. For example, you can connect parsers, and there are more choice of connected rules.



Microsoft would not be itself if it were just wanted. Whatever we say about the quality of their software, they do great development tools (and, by the way, input devices). So this time they came not empty-handed, but wrote a migration plan . In accordance with this plan, the development of tslint rules has already been discontinued on August 1, 2019, and the development of tslint itself will cease on November 1, 2019. Although, to be honest, development has been discontinued a long time ago (see above for the latest release).



Here it should become obvious to the reader that it is time to switch to eslint, there is no other choice. To sweeten the pill, it is worth saying that:





In general, it looks like the transition to a new linter, which is a mainstream product, will open up a whole world of previously unseen opportunities to us. Well, let's try it!



Add eslint to the project



I’ll talk about the migration of rules below. In the meantime, set up a project to work with eslint.

If you already have a project with tslint, then first remove all packages related to tslint from it: tslint itself, tslint-react, tslint-config-prettier, etc.



Now add the eslint packages to the project (set everything as devDependencies):





Eslint minimal setup



Create the .eslintrc.json configuration file. Eslint supports many file formats for its configuration, but JSON seems the most convenient. Here's what the minimal working option looks like:

{ //   "env": { //    "browser": true, //   ES6 "es6": true, //   ES2017 "es2017": true }, //   "extends": [ //    eslint "eslint:recommended", //      "plugin:@typescript-eslint/eslint-recommended", //    TypeScript "plugin:@typescript-eslint/recommended", //  TS,     "plugin:@typescript-eslint/recommended-requiring-type-checking" ], //   "parser": "@typescript-eslint/parser", "parserOptions": { //    TS     "project": "tsconfig.json", "tsconfigRootDir": ".", }, //      TypeScript "plugins": ["@typescript-eslint"], "rules": {} }
      
      





The env



section tells eslint about your project options. In my example, this is a project for the browser (i.e. the code will work in the browser). Write for Node.JS - set node: true. The two following options indicate the dialect of the JS being tested. In general, we will check the code for TypeScript, but if your project also has code for JS, do not forget to tighten them. For ourselves, we decided that we set these parameters to the same value as target in tsconfig.json.



There is nothing controversial in the standard eslint rule sets, such as the required semicolon at the end of expressions or spaces / tabs. All rules are uniquely useful. You can see what rules and with what level are included here .



The next line you need to disable half the rules. This is necessary because they do not work with TypeScript and instead of normal operation they will throw a bunch of errors.



Then you should connect the recommended rules from TypeScript in a separate bag. Here you need to keep in mind that general syntax rules (such as banning var) will work like that.



But for rules that use TS types (for example, @ typescript-eslint / no-unnecessary-type-assertion), the TypeScript engine is needed. And the engine will need the tsconfig.json file, the path to which must be specified.



In tsconfig.json, we at Dodo Pizza Engineering usually specify exclude and throw out tests so that they do not build with the project. But for eslint to work, you must specify and include. That is, all files that need to be linted must be explicitly included in the project. Without this, eslint will swear at every file it finds: “The file is not in the project, I won’t do anything, I’ll throw a bunch of errors.” There is an option without explicitly specifying project files - set the createDefaultProgram: true



parameter. This, in essence, means: "All that you find is Parsi." But developers strongly advise against doing so because of a significant drop in performance.



If you use ForkTsCheckerWebpackPlugin to process TypeScript files, then replace tslint: true



with eslint: true



in its parameters (in webpack.config.ts).



It is also worth setting up the launch of the linter from the command line. Before that, add this value to the scripts section in package.json



:



 "eslint": "eslint --cache --ext .js,.jsx,.ts,.tsx src", "eslint:dump": "eslint --print-config ./.eslintrc.json",
      
      





The first line just starts eslint validation without building the project. The second displays the current eslint settings, which allows you to see the settings for the rule parameters.



In this version, eslint will already work in the project and even catch some shoals: redefining globals, unused variables, etc.



Setting up Visual Studio Code



After you have gone all this way, you can already start the linter from the command line. It will also be implicitly launched when building the project. But in Visual Studio Code we will not see comments from the linter. How so ?!



There is an eslint plugin for the studio (dbaeumer.vscode-eslint), it needs to be installed. After that, nothing will work anyway, nothing will be emphasized and corrected. Why? Because the plugin has a config, which says that you need to work only in JavaScript files.



This sneaky setting is not made in the UI, so you need to go into the studio settings file and manually add the languages ​​you need to the eslint.validate parameter. A complete list of languages ​​can be found in the bowels of the studio documentation. Here's what this setting looks like with us:



 "eslint.validate": [ "javascript", "javascriptreact", "typescriptreact", "typescript", ],
      
      





After that, restart the studio and everything will finally start working.



Now it remains to configure the rules



The project is set up. Now about the rules, because in the example above the list of rules was empty.



I must say that tslint did not stop us from messing up in formally correct code. For example, forget await. Eslint knows how to find such semantic errors and swear at them: to report that the return value is Promise, but for some reason, await is not written for it. This also includes stylistic problems of medium complexity: using a lambda or function, etc., which Prettier can no longer do.



Regarding simple rules: position of brackets, tabs vs. spaces, etc., it is believed that they should be given to Prettier or a similar package. But in the linter they should be left anyway: this is the last frontier, which is still able to stop the negligent developer of the fallen project assembly. Moreover, this line can be automated: for example, husky , allows you to start the linter automatically for each commit.



We decided not to migrate any of the tslint rule sets that we have. And create your own set from scratch.



There are predefined rule sets for eslint:





We did not like any of the ready-made packages. This may sound strange, but it’s important for us to switch to a new linter, avoiding stylistic wars. If we write like this everywhere (tabs, without a semicolon, trailing commas are mandatory), then let it remain so - the main thing is that it is the same in all projects.



Promised sex: its own set of rules



Honestly, to show your eslint rule set is like a girl showing boobs: there are no more secrets. I thought for a long time whether to do this. But, after consulting with fellow girls, I decided what was worth.



I'll start with the plugins we use:





Our entire rule file is here . I note that it is not a dogma and is updated as it adapts to projects.



All Articles