Editor’s note: This article was last updated on 16 December 2022. Check out this Using Prettier and ESLint to automate formatting tutorial for more information.
As developers, we usually start a project by adding configurations and scripts for linting, then formatting and type checking for our codebase syntax and style.
This process is even more important when working on a team because everyone needs to be on the same page for codebase syntax and style. Also, to ensure that there are no typos or bugs when our app is in production, we should type-check our code along the way.
Having a formatting tool, a linting tool, and TypeScript helps us automate this process.
In this article, we’ll use ESLint and TypeScript, and we’ll also see how to add Prettier and additional tooling that will automate this process for us.
To jump ahead:
- Compiling TypeScript code
- What is ESLint?
- Linting with ESLint
- What is Prettier?
- Why do we need Prettier with ESLint?
- Integrating Prettier
Note: There is a compatibility issue with specific versions of Node and the latest versions of ESLint and Prettier, so make sure you’re running a Node version >= 16.0.0 when following the code sections later.
Compiling TypeScript code
Typescript is a superset of JavaScript that helps us with static type checking at compile time. TypeScript will give you a better development experience thanks to auto-completion in your editor. TypeScript also helps you maintain the code in your large codebases.
First, we need a compiler to turn TypeScript code into JavaScript so the browser can read it. Let’s install a dependency using your favorite package manager. Head over to a suitable folder on your computer and run one of the following commands in your terminal:
#npm npm install --save-dev typescript #yarn yarn add typescript --dev
Upon installation, you’ll see a new entry to the devDependencies
attribute of your package.json
file as:
{ "name": "Linting TypeScript with ESLint", "version": "1.0.0", "devDependencies": { "typescript": "^4.9.4" } }
If you want to verify that it’s been installed, you can run this to check the version:
npx tsc --version # Version 4.4.3
In your folder, create an index.ts
file in the src
directory and add the following TypeScript code:
// src/index.ts const favoriteFruits: string[] = ["apple", "strawberry", "orange"]; function addFruit(fruit: string) { favoriteFruits.push(fruit); }
We can compile the TypeScript code to JavaScript by running the following command in the terminal:
npx tsc src/index.ts
Right after that, we’ll see a newly generated JavaScript file in the same directory as the TypeScript file:
// src/index.js var favoriteFruits = ["apple", "strawberry", "orange"]; function addFruit(fruit) { favoriteFruits.push(fruit); }
By default, the compiler will create JavaScript files side-by-side with the TypeScript source file that created it. This is not a good idea because you’ll end up mixing your build results with your source code.
So, let’s change some default compiler settings, starting from where we want to put our compiled code, which JavaScript level is targeted to be transpiled (by default: ECMAScript 3), and which files we want to compile.
There are two ways to create your TypeScript compiler settings:
- Run the following command in the terminal:
npx ts``c
--init
. This will generate a default TypeScript configuration file - Create a file called
tsconfig.json
at the root directory of your project and include your settings
In this case, I’ll create the TypeScript compiler settings manually. However, I would encourage you to choose the first option. It will create the config file with some recommended options — all options are described with comments explaining what they do.
You can modify these settings as you need to. See the full list of supported compiler options, and you can play around in the TypeScript playground:
// tsconfig.json { "compilerOptions": { "outDir": "dist", // where to put the compiled JS files "target": "ES2020", // which level of JS support to target "module": "CommonJS", // which system for the program AMD, UMD, System, CommonJS // Recommended: Compiler complains about expressions implicitly typed as 'any' "noImplicitAny": true, }, "include": ["src"], // which files to compile "exclude": ["node_modules"], // which files to skip }
Congratulations! Now, you can start writing TypeScript and compiling it to JavaScript by running npx tsc
.
You can include the above command in your scripts to make it easier to run. Go to package.json
and add the --watch
flag to watch the files for changes. Keep in mind that everything that is described in compilerOptions
can be passed into the command line using CLI flags:
// package.json { "name": "Linting TypeScript with ESLint", "version": "1.0.0", "devDependencies": { "typescript": "^4.9.4" }, "scripts": { "dev": "tsc --watch" } }
What is ESLint?
One of the most popular tools for linting is ESLint, which will analyze your code to find potential bugs and improve your code quality by defining coding conventions and then automatically enforcing them. Let’s see how to install ESLint into our TypeScript project.
First, install the following dependencies to your devDependencies
:
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
eslint
: ESLint core library@typescript-eslint/parser
: a parser that allows ESLint to understand TypeScript code@typescript-eslint/eslint-plugin
: plugin with a set of recommended TypeScript rules
Similar to Typescript compiler settings, you can either use the command line to generate a configuration file using the --init
flag from ESLint or create it manually. Either way, it’s mandatory to have your ESLint configuration file.
Let’s create a configuration file using the CLI. Run the following command in the terminal:
npx eslint --init
Next, you will see a series of questions that allow you to adjust the configuration file based on your preferences:
- How would you like to use ESLint?
- What type of modules does your project use?
- Which framework does your project use?
- Does your project use TypeScript?
- Where does your code run?
- How would you like to define a style for your project?
Based on the options selected, the ESLint CLI will create a .eslintrc.json
configuration file in the project’s root directory with some default settings. If you already have your favorite settings, you can replace some of the options in the configuration file.
You can also explore the full list of ESLint settings available for the configuration file.
Linting with ESLint
For this article, replace the default settings in the configuration file with this:
// .eslintrc { "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 12, "sourceType": "module" }, "plugins": ["@typescript-eslint"], "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], "rules": { }, "env": { "browser": true, "es2021": true }, }
parser
: this specifies a parser for ESLint to use when analyzing the codeparserOptions
: specifies what JS language options you want to support, such as the version of ECMAScript syntax you want to useplugins
: this is where you define plugins to useextends
: tells ESLint what configuration is set to extend from. The order matters, as the last extend option will override the previous ones in any conflicting configurations.env
: which environments your code will run in
When we add an ESLint rule, it overrides the configuration defined in the extends
list. Let’s add a couple of rules to see how it works:
// .eslintrc { "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 12, "sourceType": "module", }, "plugins": ["@typescript-eslint"], "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], "rules": { "@typescript-eslint/no-unused-vars": "error", // to enforce using type for object type definitions, can be type or interface "@typescript-eslint/consistent-type-definitions": ["error", "type"], }, "env": { "browser": true, "es2021": true } }
In short, the first rule we apply is assigned to a value of error
, but error
is not the only value we can assign — we have three options:
off
or0
: turn off the rule completelywarn
or1
: treat the rule as a warning, but it won’t fail when running a lintererror
or2
: treat the rule as an error. It will fail when running a linter
Note: In some ESLint rules, like the second rule, you would need to set additional options to use an array literal syntax.
You can tell ESLint to lint your code using the following command: eslint
--ext .js,.ts
. The ext
flag is used to specify which file extensions ESLint should consider when searching for files in the target directory. In this case, we include TypeScript file extensions: .ts
(by default, it’s .js
)
Now you can add a lint
script into your package.json
with the command above:
// package.json { "name": "Linting TypeScript with ESLint", "version": "1.0.0", "scripts": { "dev": "tsc --watch", "lint": "eslint --ext .js,.ts .", }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^5.45.1", "@typescript-eslint/parser": "^5.45.1", "eslint": "^8.29.0", "typescript": "^4.9.4" } }
You’ll find that some files don’t need to be linted at all, such as your dist
folder, so you can prevent linting by creating a .eslintignore
file and adding the folders or files you want to ignore:
node_modules dist
This often matches with your .gitignore
file content, so to have a single source of truth, you can update the lint
script to use the --ignore-path
flag:
// package.json { // ... "scripts": { "lint": "eslint --ignore-path .eslintignore --ext .js,.ts ." }, // ... }
Now you’re ready to go! I suggest you integrate ESLint into whatever editor you use. If that’s VSCode, go to the extension and install the ESLint extension.
Once you’ve installed and enabled it, you’ll see what errors you’ve made in your code without running the script that is underlining with a red line.
Note: You’ll see that the ESLint error message is printed inline in the editor; that’s another extension called Error Lens, which highlights the entire line and shows the error message immediately instead of hovering with the pointer to see it:
Another feature of ESLint is that it can automatically fix code when you hover and right-click Quick fix
, or you can hit command
and +
:
Manually fixing all of the errors that have broken your rules can be tedious, but you can run the following command that will tell ESLint to fix what it can:
npm run lint -- --fix
Tip: You can pass parameters using double dashes --
for npm
scripts, which will be received as parameters for the script that npm
executes:
npm run <command> [-- <args>]
What is Prettier?
Prettier is a well-known code formatter that supports a variety of different programming languages. It helps us avoid manually formatting our code by automatically formatting it based on a specified code style.
Nowadays, it’s common to use ESLint and Prettier together, and we will learn how to integrate Prettier with ESLint. First, let’s look at the difference between both and why they can be beneficial together.
Why do we need Prettier with ESLint?
The primary function of a linter is to improve your code by analyzing it and alerting you to any potential issues based on customizable or pre-defined rulesets. These rulesets, or rules, allow development teams to maintain a consistent coding style and identify potential bugs caused by inconsistent coding styles.
On the other hand, a code formatter like Prettier ensures a consistent style by parsing your code and re-printing it according to its rules. For example, you can specify a style that all JavaScript statements must end with a semicolon; the code formatter will automatically add the semicolon to all statements without one.
In essence, you can use ESLint to specify rulesets that must be adhered to and then use Prettier to fix cases in your code where these rulesets are broken.
Integrating Prettier
With that covered, let’s add Prettier to our project; run the following command in the terminal:
npm install --save-dev prettier
Compared to ESLint, Prettier doesn’t need a config file, meaning you can run and use it straight away. However, If you want to set a config, you will need to create a file called .prettierrc
(in the project’s root directory), where you can define your format options.
More great articles from LogRocket:
- Don't miss a moment with The Replay, a curated newsletter from LogRocket
- Learn how LogRocket's Galileo cuts through the noise to proactively resolve issues in your app
- Use React's useEffect to optimize your application's performance
- Switch between multiple versions of Node
- Discover how to use the React children prop with TypeScript
- Explore creating a custom mouse cursor with CSS
- Advisory boards aren’t just for executives. Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
You can take a look at the full list of format options and can play around in the Prettier Playground:
// .prettierrc { "semi": false, // Specify if you want to print semicolons at the end of statements "singleQuote": true, // If you want to use single quotes "arrowParens": "avoid", // Include parenthesis around a sole arrow function parameter }
Next, we are going to start formatting our code using Prettier in the command line:
npx prettier --write src/index.ts # src/index.ts 37ms
I added a write
flag to overwrite the TypeScript file, otherwise, it won’t overwrite it and will only log the formatted code in your CLI.
Let’s add the Prettier command to our scripts, just as we did for TypeScript and ESLint. Let’s also support all files that end in .ts
, .js
, and .json
, and ignore the same files and directories as gitignore
(or you can create a file .prettierignore
):
// package.json { // ... "scripts": { "dev": "tsc --watch", "lint": "eslint --ext .js,.ts .", "format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\"" }, // ... }
Now, you can run the npm run format
command to format and fix all your code. But what if we would like to format the code right after saving your files?
That’s possible! In VSCode, go to the extensions
tab, look for the Prettier
extension, and ensure it’s enabled. Once enabled, we need to configure a few things in VSCode.
You can open your command palette (Command
+ Shift
+ P
) and look for Preferences: Open Settings (JSON)
. Then you’ll need to change your editor default formatter and add an extra config to format code when you save your files:
// settings.json { "editor.defaultFormatter": "esbenp.prettier-vscode", "editor.formatOnSave": true, ... }
Avoiding conflicts when working with ESLint and Prettier
You’ll likely run into an issue when a Prettier and ESLint rule overlap. You can try to auto-format your code, but it will show you some conflicts with ESLint.
The best solution here is to use a plugin eslint-config-prettier
to disable all ESLint rules that are irrelevant to code formatting, as Prettier is already good at it:
npm install --save-dev eslint-config-prettier
With that installed, let’s go to the .eslintrc
file and prettier
at the end of your extends list to disable any other previous rules from other plugins:
// .eslintrc { "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 12, "sourceType": "module", }, "plugins": ["@typescript-eslint"], // HERE "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], "rules": { "@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/consistent-type-definitions": ["error", "type"], }, "env": { "browser": true, "es2021": true } }
That’s it! Now you know how to use these static testing tools effectively. It’s great to have some automation for specific tasks like linting, formatting, and type-checking.
Conclusion
Using TypeScript and ESLint together can boost our confidence in our code. It helps us prevent bugs and can save us time in the long run. I recommend you try using TypeScript and ESLint for a better developer experience for you and your entire team the next time you’re building cool things.
LogRocket: Full visibility into your web and mobile apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.
Try it for free.
There seems to be some problems with compatibility between the latest versions of eslint and typescript-eslint, so you won’t be able to run your project with the setup suggested in this article.
Related github issue: https://github.com/eslint/eslint/issues/15149
The compatibility issues should be resolved now!