Skip to content

Using ESLint and Prettier in a TypeScript Project

Robert Cooper on February 16, 2019

Originally posted on my blog. When it comes to linting TypeScript code, there are two major linting options to choose from: TSLint and ESLint. T... [Read Full]
markdown guide

I ran a problem today with this setup. If I run prettier --single-quote --write then eslint --fix, it will fail because of this line:

                    {state === PENDING
                        ? Array(10)

prettier wants the above, but eslint wants:

                    {state === PENDING
                        ? Array(10)

(so 28 spaces instead of 30).

Any tips? I am kinda stuck.


You need to run prettier through ESLint, otherwise you'll get these kind of conflicts.


It seems that vscode is running prettier when formatting on save, rather than eslint! I will look into it on Monday when I back with my laptop :P

You need to make sure to turn off the formatOnSave in VSCode for your JavaScript and Typescript files. Here are the settings:

"editor.formatOnSave": true,
"[javascript]": {
    "editor.formatOnSave": false,
  "[javascriptreact]": {
    "editor.formatOnSave": false,
  "[typescript]": {
    "editor.formatOnSave": false,
  "[typescriptreact]": {
    "editor.formatOnSave": false,

Then to make sure you get ESLint to fix problems on save, make sure you have the following settings in VS Code:

"eslint.autoFixOnSave": true,
  "eslint.validate": [
    {"language": "typescript", "autoFix": true },
    {"language": "typescriptreact", "autoFix": true }

Thanks! But there is still an issue with it :( It seems like a conflict between eslint(prettier/prettier) and eslint(@typescript-eslint/indent). I also feel like eslint is running twice or something. For now I have set:

    rules: {
        '@typescript-eslint/indent': 'off',

Here's my full eslint config file:

module.exports = {
    parser: '@typescript-eslint/parser',
    extends: [
    parserOptions: {
        ecmaVersion: 2018,
        sourceType: 'module',
        ecmaFeatures: {
            jsx: true,
        project: './tsconfig.json',
        tsconfigRootDir: './',
    settings: {
        react: {
            version: 'detect',
    rules: {
        '@typescript-eslint/interface-name-prefix': 'always',
        '@typescript-eslint/no-explicit-any': 'always',
        '@typescript-eslint/explicit-function-return-type': 'off',
        '@typescript-eslint/no-non-null-assertion': 'off',
        '@typescript-eslint/no-use-before-define': 'off',
        '@typescript-eslint/member-delimiter-style': {
            delimiter: 'none',
            requireLast: true,

VSCode User settings:
VSCode Workspace settings:

I think your extends array should be the following (I've added comments explaining things):

    extends: [
        'plugin:@typescript-eslint/recommended', // uses typescript-specific linting rules
        'plugin:react/recommended', // uses react-specific linting rules
        'plugin:prettier/recommended', // enables eslint-plugin-prettier and eslint-config-prettier
        'prettier/react', // disables react-specific linting rules that conflict with prettier

Still didn't seem to fix the issue! Although I also ran into this last week, which I have not been able to solve. Something must be wrong with my setup somewhere haha. Check it out:

Prettier wants this:

export default function Heading(
    props: HTMLProps<HTMLHeadingElement> & {
        as?: AsTags
        withComponent?: HeadingTags
) /* .... */

But typescript fails to compile because of the missing comma after as?: AsTags as it wants as?: AsTags, but prettier removes it ._.

Thanks for providing the snippets though. If you can shed any light on this one I would appreciate it a ton :3


Just curious about your opinion on if you need to use a linter to check code if you use typescript in strict mode. For styles, for sure using prettier makes sens to me.


Good question. Using a linter allows you to check on a lot of stuff that isn't covered by the TypeScript compiler. For example, if you take a look at some of these ESLint rules for TypeScript code, you'll find a lot of rules related to code style that can be enforced with a linter.

Here are a few examples:

  • @typescript-eslint/explicit-function-return-type: Require explicit return types on functions and class methods
  • @typescript-eslint/generic-type-naming: Enforces naming of generic type variables
  • @typescript-eslint/no-array-constructor: Disallow generic Array constructors
  • @typescript-eslint/no-unused-vars: Disallow unused variables

all of the rules above are again kinda of stylistic (last one is already covered directly by typescript). If something is wrong, typescript will tell u during compile regardless whether you specify function return type explicitly or not.. I also depend on computer types in typescript (maybe thats why i think like this for linter with strict mode)

Well if you don't mind having the code written in a project not conform to code style rules, then a linter is of no value. You just might have a large variance in the way code is structured/ordered, variables are named, and other code style related things.

When I'm working on a project, I prefer to look at the code base and have it look like it was all written by the same person. A linter helps achieve this in my opinion.

And there's still things like no explicit any that can be enforced by the linter.


Apparently .eslintrc (as a JSON file) can contain JS-style comments. That's helpful to me, because Visual Studio 2017 seems happiest with JSON rather than JS.


Ah interesting, thanks for pointing that out Michael.


Thanks for the great article. I was just busy on writing something similar on getting Gatsby set-up with TypeScript, ESLint, and Prettier. The set-up is pretty similar as well!

Never mind the question below, it's the eslint.validatesetting in VS code :D, I should've taken a note from your article ;).

Question for reference:

I wonder if you've encountered the same thing though: In VSCode, the editor doesn't seem to show me errors from my ESLint file with this setup, whether they're an extension of rules or added explicitly, just the TypeScript errors. Of course, when linting the errors _do show up. Any ideas on how to fix this?_


Just took a peak at your article. Great write up 👍🏼


I'm glad this was linked because the article was missing the crucial step of adding --ext js,jsx,ts,tsx to the npm run script.


Thanks so much Robert! Hope I've got some time to publish part 2 soon


In VSCode I get a ts error like this photo ( but if I run eslint by itself it does not report on it.

pwd$ ./node_modules/.bin/eslint --fix src/

So my pre commit hooks do not bail out correctly as they always seem to pass. Surely I must be missing something?


ESlint doesn't check for TypeScript errors, so if you want to check for TypeScript errors in your pre commit hook, you'll need to run the tsc --noEmit command in addition to the ESLint command.

Here's a pre commit command that you could use:

"husky": {
    "hooks": {
        "pre-commit": "tsc --noEmit && eslint --fix src/"

However, I would suggest using lint-staged so you don't have to run the eslint command on all the files in your src/, but rather only run it on files that are staged to be committed. This will save you time.

"husky": {
    "hooks": {
        "pre-commit": "tsc --noEmit && lint-staged"
"lint-staged": {
    "*.{js,ts,tsx,jsx}": [
        "eslint . --fix",
        "git add"

Oh well that makes total sense. I though eslint with ts was doing tslint, and I thought tslint would do these kind of checks.

Many thanks, and yeah, I went with the section option:

    "lint-staged": {
        "src/**/*.{tsx,js}": [
            "prettier --single-quote --write",
            "eslint --fix",
            "git add"

Thank you Robert for the easy-to-follow article & bitten for adding the prettier option.

I was able to get the eslint & prettier set up for my pet project after following this post & the comments.

cshooks / hooks

List of all React hooks using data structures and algorithms


All Contributors Known Vulnerabilities

A collection of React Hooks using Computer Science (CS) data structures & algorithms.


Mainly to learn CS data structure & algorithms
(and also implement'em in TypeScript).

Hopefully some of the arcane data structures & algorithms help you as well.



Returns a Trie data structure, which is used to save a list of words to search in memory efficient manner & provide a type-ahead (not yet implemented) functionality.


Thanks goes to these wonderful people (emoji key):

This project follows the all-contributors specification. Contributions of any kind welcome!


Thanks! It works perfectly!

Here's what I ended up with, since your examples don't build up (I mean the React config is lost after just being introduced :P):

module.exports = {
  parser: "@typescript-eslint/parser", // Allows ESLint to lint TypeScript.
  extends: [
    "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
    "plugin:@typescript-eslint/recommended", // A plugin that contains a bunch of ESLint rules that are TypeScript specific.
    'prettier/@typescript-eslint',  // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
    'plugin:prettier/recommended',  // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: "module",
    ecmaFeatures: {
      jsx: true, // Allows for the parsing of JSX
  env: {
    es6: true,
    browser: true,
    node: true,
  rules: {
    // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
    // e.g. "@typescript-eslint/explicit-function-return-type": "off",
  settings: {
    react: {
      version: "detect", // Tells eslint-plugin-react to automatically detect the version of React to use

And of course, I disabled VSCode's onsave formatter, thanks for that catch! Could have driven me mad... :)


Thank you, Robert. This was quite educational.

Especially because I've recently moved to TSLint without knowing about the the TypeScript 2019 roadmap and being a TypeScript newbie :).


Ya, I was using TSLint before recently switching to ESLint for TypeScript. TSLint works well, but I found myself missing certain rules that were available in ESLint, but not TSLint.


I'm battling a little bit with this one.. In addition to the typical src/ folder, my project also has a scripts/ folder which contains custom JS based build/test/release helper scripts to run with Node.

I placed an .eslintrc file in the project root with the TypeScript configuration, which appears to be working fine, but regardless of what I do in the scripts/.eslintrc file, the linter keeps trying to apply my TypeScript rules to my JaveScript files.

Isn't ESLint supposed to use the closest config file when linting subfolders? Is there any way to explicitly tell it do so?


Although I had configured Prettier and ESLint, I still need to add this rule in .eslintrc to have single quotes and no semicolon.

'prettier/prettier': ['error', { singleQuote: true, semi: false }],

If I remove this part { singleQuote: true, semi: false }, the editor will yell when I use single quotes or no semicolon.

This is my .prettierrc:

module.exports = {
  semi: false,
  trailingComma: 'es5',
  singleQuote: true,
  printWidth: 100,
  tabWidth: 2,

This is my .eslintrc extends:

extends: [

According to this article, those 2 above should be enough.

Do you know why?


Nice write up! I'm using something pretty similar in my project, however I have noticed on larger typescript projects that the eslint.autoFixOnSave feature stops working correctly with this setup if I set my eslintrc to point to my tsconfig in parserOptions.

I haven't figured out exactly whats going on, it could be something funky in my tsconfig


Not sure what could be causing your issue. I’ve got this setup working for a large project written in TypeScript and it works without issue.


Seems to maybe be a performance issue with @typescript-eslint/parser. It only affects some projects and they are still investigating the root issue.


Don't you also need to add these plugins to the plugins section in the config file?

How would you also add eslint-config-airbnb to this? It also requires eslint-plugin-import and eslint-plugin-jsx-ally.


Hi. I've added the config as below:

"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"

When I run "eslint --fix lib" it says

"Oops! Something went wrong! :(

ESLint: 6.8.0.

No files matching the pattern "lib" were found.
Please check for typing mistakes in the pattern."

All my files are in typescript which I migrated from javascript. The same command works for old .js files' directory but not the current new one.

Any advice?


Thanks for the helpful post. I used this to make sure I didn't miss anything in mine. The extends were key for me.

Here is my repo in case anyone wants another reference


Awesome! Glad you found it helpful 👍🏼


THANK THE LORD FOR THIS! Eslint information is hard to decipher and this set up works great! Prettier is so simple and I'm glad to see that it can be leveraged with the ESlint engine.

I refer to this article everytime I start a project.. maybe it's time I start a template? ty xx


Hi Robert, i'm trying to implement typescript and eslint to my existing nextjs project
Somehow I got error:

Cannot read config file: /Users/jason/project/<ProjectName>/node_modules/@typescript-eslint/eslint-plugin/dist/index.js Error: Cannot find module 'typescript' Referenced from: /Users/jason/project/<ProjectName>/.eslintrc.js

and for now every warning is still coming from tslint (as the warning come with ts(<code>))

I don't have idea why is that happen, can u help me or at least give me some insight?


The error says you don't have typescript installed as a project dependency.

Also, tslint will continue displaying errors if you have a tslint configuration file in your repository, so just get rid of that file. It might be worth disabling tslint in your VSCode settings (you can disable it for your workplace settings only rather than globally under your user settings).

Hopefully that helps!


Thanks for the article I've just converted my TS node project to this setup!


I feel this article should be entitled "how to React with React and React".


Thanks for the article! I've setuped Prettier with ESLint, but I'm thinking if there is a way to specify settings.json per project as I don't want to run eslint of every project I open and save.


Very helpful! I've used typescript but I'm a newbie to eslint and prettier. I understand them much better now. Thanks!

code of conduct - report abuse