# 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](https://hashnode.blainegarrett.com/building-a-github-repo-template-part-1-nextjs-react-and-typescript-ckcnovxex003bjos1632n4g9a), I demonstrated how to set up the base Next.js app written in TypeScript. In this post, I will cover linting with [ESLInt](https://eslint.org/) 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](https://github.com/blainegarrett/react-next-material-typescript-template/compare/0.0.1...0.0.2) or check out the [0.0.2 release of the repository](https://github.com/blainegarrett/react-next-material-typescript-template/releases/tag/0.0.2).

## Prerequisites 
- If you are following along, please complete [part 1 of the series](https://hashnode.blainegarrett.com/building-a-github-repo-template-part-1-nextjs-react-and-typescript-ckcnovxex003bjos1632n4g9a). I am immediately picking up where that post left off. 
- I am using [VSCode](https://code.visualstudio.com/) 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](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb) 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](https://medium.com/palantir/tslint-in-2019-1a144c2317a9). 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](https://cdn.hashnode.com/res/hashnode/image/upload/v1594844811969/Z9uHKdYxU.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](https://cdn.hashnode.com/res/hashnode/image/upload/v1594846321845/0ipaFIHlX.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](https://cdn.hashnode.com/res/hashnode/image/upload/v1594848126361/z2z-bvVvm.png)

![Screen Shot 2020-07-15 at 4.21.33 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1594848132626/gQe7DYHlQ.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](https://hashnode.blainegarrett.com/building-a-github-repo-template-part-3-jest-testing-setup-with-typescript-ckcp0cssw000btvs14e88fws4). If you are following along, [you can view the full PR for this changeset](https://github.com/blainegarrett/react-next-material-typescript-template/pull/2/files) or check out the [0.0.2 release of the repository](https://github.com/blainegarrett/react-next-material-typescript-template/releases/tag/0.0.2).

## 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](https://hashnode.blainegarrett.com/making-eslint-happy-in-mixed-typescriptjavascript-projects-ck5lge2v204cgqks1sk4nlp85).

Image Credit: "[Strawberries in boxes](https://www.flickr.com/photos/55216729@N06/43469235671)" by [Government of Prince Edward Island](https://www.flickr.com/photos/55216729@N06) is licensed under [CC BY-NC-ND 2.0](https://creativecommons.org/licenses/by-nc-nd/2.0/?ref=ccsearch&atype=rich)
