Building a Github Repo Template Part 2: ESLint with TypeScript

In this ongoing series, I am putting together a Github Repository Template for my "Go To" front-end tech stack of Next.js, React, TypeScript etc. In part 1 of the series, I demonstrated how to set up the base Next.js app written in TypeScript. In this post, I will cover linting with ESLInt and auto formatting.

Code linting is the practice of scanning code for potential errors. It also can enforce code standards such as indents, when to use quotes, etc. Most IDEs (such as VSCode) will leverage linting to highlight syntax issues right in the IDE and even fix them. This saves a lot of time and is a great developer experience especially if you are on a team. For me, it is as important an aspect of software development as unit testing (covered in Part 3 of the series).

Just want the Code? View the full changeset in this Github PR or check out the 0.0.2 release of the repository.

Prerequisites

  • If you are following along, please complete part 1 of the series. I am immediately picking up where that post left off.
  • I am using VSCode for my IDE and several parts of this post refer to VSCode specific things. If you are not using VSCode, I highly recommend it. After years of using Sublime, Atom, WebStorm, I feel like VSCode "just works".

Installing ESLint

First, locally install the ESlint dependency to our project.

npm install --save-dev eslint

Next, I need to initialize ESLint and install the Airbnb presets which is a great starting point for our linting rules

eslint --init

Follow the prompts to:

  • select "❯ Use a popular style guide"
  • select "Airbnb" as the base
  • Enter, yes you are using React
  • Finally, allow the initializer to save the config file This will likely prompt to install some additional dependencies

This will generate a file in the project root eslintrc.json that contains only:

{
    "extends": "airbnb"
}

We will need to modify this file shortly to extend ESLint to support TypeScript.

The airbnb presets are handy and will include everything we need including support for React Hooks, etc.

Next, modify our package.json to include a linting command.

  "scripts": {
     ...
    "lint": "eslint . --ext .ts,.tsx",
     ...
  },

This will programmatically run the local ESLint dependency against all files with extensions .ts or .tsx.

Running the following in the command line:

npm run lint

give us the error:

error  Parsing error: The keyword 'interface' is reserved

This means we need to install some additional things for ESLint to understand TypeScript. The keyword "interface" was from me defining a type for our IndexPageProps. Since "interface" is a TypeScript specific syntax feature, we need ESLint to understand it.

//pages/index.tsx 
...
interface IndexProps { // This is the line eslint is failing on because it doesn't speak TS yet
  greeting: string
}
...

Installing ESLint TypeScript dependencies

Note: tslint used to be the preferred way to lint TypeScript for years but has been deprecated. TypeScript support for ESLint has come a long long way and I have been quite happy with it.

To install the TypeScript dev dependencies, simply run:

npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin

Next, I need to tell ESLint to use the plugin. Modify the eslintrc.json generated when initializing ESLint to look like:

{
    "extends": [
        "airbnb",
        "plugin:@typescript-eslint/recommended"
    ]
}

Now when running npm run lint, a bunch of formatting errors are produced. This is good! I'll leave them for now and get auto-format-on save to magically clean up most of them for me in the next steps.

Screen Shot 2020-07-15 at 3.21.18 PM.png

Auto Formatting

I'll leverage VSCode's settings to automatically clean these issues up.

In your project root, create or modify the .vscode/settings.json file. Here is mine currently for comparison sake.

{
    "files.exclude": {
      ".git/": true,
      "node_modules/": false,
      ".next/": false
    },
    "search.exclude": {
      "**/node_modules": true,
      "**/.next": true
    },

    // Personally I like 80 for readability but enforce 100
    "editor.rulers": [80, 100, 120],
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    }
  }

The critical directive to Auto Format on save is:

    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    }

Open up the pages/index.tsx file in VSCode and notice all the ESLint errors highlighted. Mine looks like a sea of red: Screen Shot 2020-07-15 at 3.51.50 PM.png

Now, hitting save, most of our errors go away! If I run npm run lint, I will see a far shorter list. The critical remaining error needing attention is the React sytnax error.

  14:5   error    JSX not allowed in files with extension '.tsx'         react/jsx-filename-extension"

I need to tell ESLint it is OK to allow React's JSX syntax in files other than those with the .jsx extension. I also need to tell ESLint to understand module extension ending in ts or tsx. This can be resolved by adding a rules directive to the eslintrc.config

{
  "extends": [
    "airbnb",
    "plugin:@typescript-eslint/recommended"
  ],
  "rules": {
    "react/jsx-filename-extension": [1, { "extensions": [".tsx"] }],
    "import/extensions": [
      "error",
      "ignorePackages",
        {
          "js": "never",
          "jsx": "never",
          "ts": "never",
          "tsx": "never"
        }
    ]
   },

  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".ts", ".tsx"]
      }
    }
  }
}

Aside from the line length warning, all of the ESLint errors are gone. For now I will ignore the unused variable warning.

Screen Shot 2020-07-15 at 4.21.47 PM.png

Screen Shot 2020-07-15 at 4.21.33 PM.png

Closing Thoughts

At this point the Github Template repository contains a Next.js application written in TypeScript that obeys airbnb formatting rules without any errors. That might be a good starting point for most people, but in the next post, I will get Jest Testing set up. If you are following along, you can view the full PR for this changeset or check out the 0.0.2 release of the repository.

Discussion Topic

I didn't leverage Prettier in this post. I'm unclear any more if Prettier is needed. Feel free to post in the comments your feelings on Prettier. Note: If you find yourself needing to run ESLint in a mixed TypeScript and Javascript environment, see my previous hashnode post on the topic.

Image Credit: "Strawberries in boxes" by Government of Prince Edward Island is licensed under CC BY-NC-ND 2.0

No Comments Yet