Improving Code Quality in React with ESLint, Prettier, and TypeScript
A Step-by-Step Guide
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
andconst
) 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 ruleno-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.