We all write solid code, right? Of course we do, and of course, we don’t. No matter your experience with JavaScript and TypeScript and how well your typings are, there are still common pitfalls that should be avoided or better syntaxes that should be used. Not only that, but code styling should be kept normalized throughout a codebase that may have different developers.
NEW RESEARCH: LEARN HOW DECISION-MAKERS ARE PRIORITIZING DIGITAL INITIATIVES IN 2024.
Tools like ESLint and Prettier can help automate and assert that code style be the same, and common pitfalls are caught. These tools can also be integrated within your workflow and more than likely right in your editor helping while you are writing the code.
Prettier
First, let’s talk about Prettier. Prettier is more of a code style type of tool where you can tell it your spacing, whether you want to use semicolons, what quotation you prefer and other things. I’ve seen code that mixes tabs with spaces with varying numeration of each with a mix of single and double quotes, and I then have to work more to understand the code I’m reading. This isn’t optimal so you can run Prettier over code to assert these different options and Prettier can even fix these things for you. To get started, we need to first install it using npm locally in your project:
npm install --save-dev --save-exact prettier // or with yarn: yarn add --dev --exact prettier
Prettier has its defaults but you can change these values via a .prettierrc
file located in the root of your project. An example configuration I commonly use is:
{ "parser": "typescript", "printWidth": 120, "singleQuote": true, "trailingComma": "all" }
You can view what options and their defaults here. A script in the package.json
should be used so you can easily target the locally installed instance:
"scripts": { "prettier": "prettier 'src/**/*.ts'", "prettier:fix": "prettier --write 'src/**/*.ts'" }
And you can run that script:
npm run prettier // or with yarn: yarn prettier
And if you wanted to have Prettier automatically fix the issues it found, you can use the prettier:fix
script.
ESLint
ESLint is a configurable and pluggable tool that lints your code based on rules. These rules are where the power of ESLint comes from and enables a wide range of code analysis and assertion. This assertion can be enforcing code standards for style and syntax. For example, take this code:
const myMap = ['foo', 'bar']; for (const key of myMap) { // ... }
ESLint sees the for...of
loop and knows it can cause poor performance and throws this error:
iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.
ESLint plugins can add additional rules to the out-of-the-box rules that ESLint provides. Plugins can also provide configurations that ESLint can extend so that they can be used on different projects yet provide the same functionality. Two popular configurations are Airbnb and Standard.
To install ESLint, there are several other modules you’d need (since you’ll need to use different plugins and configuration sets):
npm install --save-dev --save-exact eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-airbnb // or with yarn: yarn add --dev --exact eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-airbnb
To configure ESLint, you can define the configuration in the .eslintrc.json
and would look something like:
{ "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "airbnb" ], "parser": "@typescript-eslint/parser", "plugins": ["@typescript-eslint"], "rules": { "@typescript-eslint/indent": ["error", 2], "@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-explicit-any": "error" } }
The extends
configuration tells ESLint what configuration sets to extend from. The order in this array is the order the configuration sets will be applied so the last one wins for any conflicting configurations.
The parser
configuration tells ESLint to run the code through a parser when analysing the code as by default it uses the Espree parser which won’t know how to understand the typings and possibly newer syntax that TypeScript supports.
The plugins
array is where you’ll define which plugins to use.
The rules
object is where you can override other rules applied by the configuration sets defined in the extends
config.
For more about the different configurations, please see the ESLint documentation.
Like we did with Prettier, we can define two scripts in package.json
to work with ESLint:
"scripts": { "eslint": "eslint 'src/**/*.ts'", "eslint:fix": "eslint --fix 'src/**/*.ts'" }
ESLint + Prettier
We saw how to work with ESLint and Prettier individually but since ESLint is pluggable, we can use Prettier within ESLint. To do this, we need to install the configuration set and plugin:
npm install --save-dev --save-exact eslint-config-prettier eslint-plugin-prettier // or with yarn yarn add --dev --exact eslint-config-prettier eslint-plugin-prettier
To use these two modules, we need to add two configuration sets to ESLint’s extends
array, the plugin to the plugins
array and a rule. The new .eslintrc.json would look like:
{ "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "airbnb", "plugin:prettier/recommended", "prettier/@typescript-eslint" ], "parser": "@typescript-eslint/parser", "plugins": ["@typescript-eslint", "prettier"], "rules": { "prettier/prettier": "error", "@typescript-eslint/indent": ["error", 2], "@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-explicit-any": "error" } }
Now when you run the eslint script, Prettier errors will now be ESLint errors and you no longer have to run the Prettier scripts and can remove them from the scripts object.
Git Integration
As I said before, ESLint can fit in your workflow, and part of the workflow I will assume is checking source into a git repository. What we would want is before creating a commit, run ESLint, and if there is an error prevent the commit from happening. This can catch errors early and before it makes it into the repository. To do this, we need to install two modules:
npm install --save-dev --save-exact husky lint-staged // or with yarn yarn add --dev --exact husky lint-staged
Husky will create git hooks as defined in your package.json
(or the separate husky config file):
"husky": { "hooks": { "pre-commit": "yarn lint-staged" } },
On the pre-commit hook, it will run yarn lint-staged
command. Lint-staged also needs to be configured in package.json
(or the separate lint-staged config file):
"lint-staged": { "src/**/*.ts": [ "eslint --fix", "git add" ] },
Now when you attempt to create a commit, all TypeScript files will have ESLint run on them and automatically fix any issues, it can automatically fix and add them to the commit automatically for you. If there are errors, ESLint cannot automatically fix them, and the commit will be prevented, requiring you to fix these errors before a commit can be created.
Editor Integration
Wouldn’t it be great if you could see errors from ESLint as you write code? I bet the editor you use has support for integrating ESLint; we’ll focus on VSCode for this blog. Luckily there are plugins for VSCode for ESLint and Prettier. Once installed, and I recommend adding these to your .vscode/extensions.json file, code written in VSCode will run ESLint on the file. It will run ESLint using the configuration you wrote before. If there are any errors, there will be a red squiggly line under the erroneous code; if there are any warnings, the line will be yellow. You can move your mouse over the code, and it will show the error(s)/warning(s) allowing you to see what rule is being broken so you can then change the code.
Conclusion
TypeScript gives you the ability to have strong typing, which can catch some issues; however, it won’t catch everything. TypeScript also doesn’t give you the ability to control the code style. With the help of tools like ESLint and Prettier, we allow for catching more issues and control the code style across a team. And with Husky, lint-staged and editors like VSCode, we can integrate ESLint and Prettier into our workflow in an automatic and automated way.
ESLint has lots of plugins, what are some plugins you use in your projects?
Mitchell Simoens
Related Posts
-
Code Splitting for React Router with ES6 Imports
Partial application loading is an essential technique for improving the time-to-first-impression for single page applications.…
-
Publishing TypeScript Modules to NPM
The rise of open source has given developers countless new languages to choose from. TypeScript…