Improving Code Quality in React with ESLint, Prettier, and TypeScript

A Step-by-Step Guide

Saurabh Lende
Globant
7 min readMar 31, 2023

--

In this blog post, I'll explain what each tool does and how to set them up in your project. These tools will help you catch errors and ensure your code is consistent and easy to read.

What Are ESLint, Prettier & TypeScript?

Let's go through the brief introduction and understand the benefits of each tool:

  • ESLint is a static code analysis tool that helps identify and fix problems in your code. It enforces rules to ensure your code is consistent and follows best practices. For example, in Javascript variables are declared using var and functions are hoisted, so it is possible to use identifiers before their formal definition in code. However, if you declare the blocked scoped variables (variables that are declared usinglet and const) will be in a temporal dead zone, and if you try to access those variables before their definition, ReferenceError will be thrown. To avoid this, ESLint's rule no-use-before-define warns when it encounters an identifier that has not yet been declared.
  • Prettier is a code formatter that automatically formats your code to follow a consistent style. It helps keep your code readable and maintainable. As an example, you can visit Prettier's playground.
  • TypeScript is a superset of JavaScript that adds type annotations to your code. It helps catch errors at compile time and improves code documentation. For example, a common bug in JavaScript is when you pass a variable with the wrong type. Typescript is strictly typed, so it eliminates the possibility of those types of bugs.

The following steps will guide you on how to set up ESLint, Prettier, TypeScript, and React in your project.

1. React Application Setup with TypeScript

Create a new React app using the create-react-app command:

npx create-react-app my-app --template typescript

The parameter --template typescript is used to create a React TypeScript project instead of JavaScript.
After this do npm install for the initial react library/dependencies installation.

2. ESLint Installation and Setup

To use ESLint in your project, you first need to install it as a dev dependency:

npm install eslint --save-dev

Initialize the ESLint:

npx eslint --init

This command will start the process of ESLint initialization

? How would you like to use ESLint? ...
To check syntax only
> To check syntax and find problems
To check syntax, find problems, and enforce code style

Choose "To check syntax and find problems" as we will employ prettier to enforce the code's formatting.

? What type of modules does your project use? ...
> JavaScript modules (import/export)
CommonJS (require/exports)
None of these

Choose "JavaScript", as React uses it

? Which framework does your project use? ...
> React
Vue.js
None of these

Select "React" from the options

? Does your project use TypeScript? » No / Yes

Select "Yes" for TypeScript

? Where does your code run? ...  (Press <space> to select, <a> to toggle all, <i> to invert selection)
√ Browser
√ Node

Choose "Browser"

? What format do you want your config file to be in? ...
JavaScript
YAML
> JSON

Choose JSON; I am choosing JSON because of the familiarity otherwise, you can go for other config file formats as well.

After this step, it will ask for the installation of dependencies

The config that you've selected requires the following dependencies:


eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
? Would you like to install them now? » No / Yes
? Which package manager do you want to use? ...
> npm
yarn
pnpm

It will start installing eslint-plugin-react@latest, @typescript-eslint/eslint-plugin@latest, @typescript-eslint/parser@latest .

And as an output of this process, a .eslintrc.json file will be created which is a configuration file used by ESLint to enforce consistent coding styles. I will share more details about the content of .eslintrc.json in the upcoming section after the setup is complete. For more details about the ESLint configuration files, refer to this.

3. Prettier Installation and Setup

Install Prettier as a dev dependency

npm i -D prettier eslint-plugin-react-hooks

I have also installed eslint-plugin-react-hooks along with prettier which will enforce the rules for React Hooks.

Create .prettierrc.json and add the below lines in it. This file is a configuration file of Prettier. The below code sets the use of a trailing comma for compatibility with ES5, a tab width of 4, the omission of semicolons, and the use of single quotes. For more details about the Prettier configuration files, refer to this.

{
"trailingComma": "es5",
"tabWidth": 4,
"semi": false,
"singleQuote": true
}

Create .prettierignore and add this in .prettierignore. It contains files and directories to be ignored by the Prettier.
This specific file ignores the node_modules directory as well as the build and Coverage directories which are considered artifacts. So that code style won't be forced on artifacts.

node_modules
# Ignore artifacts:
build
Coverage

4. Making ESLint and Prettier work together

The only difficulty of using both ESLint and Prettier together is that they have different code formatting approaches. This can lead to conflicts between the two tools.
To make it easier to use both ESLint and Prettier together, you can use the ESLint plugin for Prettier. This plugin will combine Prettier's formatting rules with ESLint to ensure your code is appropriately formatted and follows your coding standards.

npm install --save-dev eslint-config-prettier eslint-plugin-prettier

Note: eslint-config-prettier will disable the ESLint formatting rules and eslint-plugin-prettier will enforce ESLint to use formatting rules for Prettier.

Understanding the ESLint Configuration File

After adding a few configurations to the .eslintrc.json file it will look like this:

{
"env": {
"browser": true,
"es2021": true,
"jest": true
},
"extends": [
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"plugin:prettier/recommended",
"plugin:import/recommended"
],
"overrides": [],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [ "react", "@typescript-eslint", "react-hooks" ],
"rules": {
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": [ "error" ],
"react/jsx-filename-extension": [ "warn", { "extensions": [ ".tsx" ] } ],
"import/extensions": [ "error", "ignorePackages", { "ts": "never", "tsx": "never" } ],
"no-shadow": "off",
"@typescript-eslint/no-shadow": [ "error" ],
"@typescript-eslint/explicit-function-return-type": [ "error", { "allowExpressions": true } ],
"max-len": [ "warn", { "code": 100, "ignoreComments": true, "ignoreUrls": true } ],
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"import/prefer-default-export": "off",
"react/prop-types": "off",
"prettier/prettier": [ "error", { "endOfLine": "auto" } ]
},
"settings": {
"import/resolver": {
"typescript": {}
}
}
}

I'll try to explain the file format in brief

  • env: This section specifies the environment in which the code will run in. In this case, it specifies that the code will run in a browser and use ES2021 features. Add “jest”: true if you intend to use JEST.
  • extends: This section extends the configuration of other ESLint plugins. It extends the recommended React configuration and the recommended TypeScript configuration.
  • parser: This section specifies the parser to use for parsing the code. In this case, it specifies the TypeScript parser.
  • parserOptions: This section specifies the parser options. In this case, it specifies that the code uses ECMAScript 2021 syntax, the source type as a module, and that it includes JSX syntax.
  • plugins: This section specifies the ESLint plugins to use. In this case, it specifies the React, TypeScript, and React Hooks plugins.
  • rules: This section specifies the ESLint rules to use. I'll add the details about the rules that I have used in the above .eslintrc.json file in the next section.
  • settings: This section specifies the settings for the ESLint plugins. In this case, it specifies the TypeScript resolver.

I will also add the details about the rules that I have used in the above .eslintrc.json

  • no-use-before-define: Turn off the ESLint rule that disallows using variables before they are defined.
  • @typescript-eslint/no-use-before-define: Turn on the TypeScript ESLint rule that disallows using variables before they are defined.
  • react/jsx-filename-extension: Show a warning if a file using JSX doesn't have a .tsx extension.
  • import/extensions: Show an error if an imported file doesn't have a .ts or .tsx extension, except for packages.
  • no-shadow: Turn off the ESLint rule that disallows variable shadowing.
  • @typescript-eslint/no-shadow: Turn on the TypeScript ESLint rule that disallows variable shadowing.
  • @typescript-eslint/explicit-function-return-type: Show an error if a function's return type is not explicitly defined unless it's an expression.
  • max-len: Show a warning if a line of code is longer than 100 characters, ignoring comments and URLs.
  • react-hooks/rules-of-hooks: Show an error if React hooks are not used correctly.
  • react-hooks/exhaustive-deps: Show a warning if the dependencies in a useEffect hook are not exhaustive.
  • import/prefer-default-export: Turn off the ESLint rule that requires a default export when there is only one named export.
  • react/prop-types: Turn off the ESLint rule that requires prop types to be defined for React components.
  • prettier/prettier: Show an error if the code does not conform to Prettier's formatting rules.

To verify the above setup we need to setup scripts in package.json

"scripts": {
...,
"lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"",
"lint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\"",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,md}\" --config ./.prettierrc.json"
}

In addition to this, if you want to use Airbnb coding styles, previously it was part of the ESLint setup (which is well explained here) but as of now, Airbnb is not part of the ESLint setup, so we need to install an additional package to use those coding standards.

npm i eslint-config-airbnb

In .eslintrc.json add Airbnb in extends

"extends": [

"airbnb"
]

This will force ESLint to use the coding standards of Airbnb.

VS Code: Setting up automatic ESLint + Prettier fix on file save

If you will use VS Code then this setting is very helpful. Go through this article. This will auto-format the code by running ESLint whenever you save the file.

Conclusion

Using ESLint and Prettier with TypeScript and React can improve code quality and catch errors early on. Customizing rules can ensure efficiency and maintainability. Despite setup difficulty, the investment leads to a streamlined development process and a better end product.

--

--