by Francesco Agnoletto

How to setup gatsby with TypeScript and ESLint + prettier

The best tools for react development on vscode

Official Gatsbyjs logo

Gatsbyjs starters are perfect for jumpstarting a new project. As all boilerplates, it lacks some tools to optimize our development experience.
Fortunately for us, Gatsbyjs is highly customizable.

TypeScript

Typescript is the easiest of them and the most impactful. Install the TS package, add it to the gatsby-config.js file, and create a tsconfig.json file.

// basic gatsbyjs tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    "target": "esnext",
    "jsx": "preserve",
    "lib": ["dom", "esnext"],
    "strict": true,
    "noEmit": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "noUnusedLocals": false
  },
  "exclude": ["node_modules", "public", ".cache"]
}

You can now start converting JS files to TS. Remember to add the @types/ packages, as by default they are not included.

As a bonus, install typescript and add a type check script to your package.json.

"type-check": "./node_modules/typescript/bin/tsc --noEmit --skipLibCheck"

Gatsby and gatsby-plugin-typescript use babel, so type checking will not stop the build. Use the script either manually or as a pre-commit hook to run it automatically.

Prettier

Like TypeScript, prettier is pretty straight-forward. One of the most used starters, gatsby-starter-blog already includes it. Let’s see how to add it from scratch.

We have to install prettier as dev dependency npm i -D prettier. After that, a simple .prettierrc file will suffice.

// .prettierrc
{
  "endOfLine": "lf",
  "semi": true,
  "singleQuote": false,
  "tabWidth": 2,
  "trailingComma": "es5"
}

Install the prettier plugin on vscode and enable it on your personal settings.json file. View -> command palette -> search for ”> preferences: open settings (JSON)“.

// settings.json rules for prettier
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": false
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": false
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": false
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.formatOnSave": false
  }
}

ESLint

ESLint requires a bit more than the other two. First, we need to install all the dev deps needed to run it. We will need eslint, eslint-loader, and gatsby-plugin-eslint for the initial config.
eslint-plugin-react for react, eslint-plugin-prettier and eslint-config-prettier for prettier. @typescript-eslint/eslint-plugin and @typescript-eslint/parser for TypeScript compatibility.

$ npm i -D eslint eslint-loader gatsby-plugin-eslint eslint-plugin-react eslint-plugin-prettier eslint-config-prettier @typescript-eslint/eslint-plugin @typescript-eslint/parser

Open gatsby-config.js and add the ESLint config to make it work. We need to allow TS extensions and optimize a couple of options.

// gatsby-config.js with eslint for both JS and TS files
{
  ...
  plugins: [
    ...,
    {
      resolve: "gatsby-plugin-eslint",
      options: {
        test: /\.js$|\.jsx$|\.ts$|\.tsx$/,
        exclude: /(node_modules|.cache|public)/,
        stages: ["develop"],
        options: {
          emitWarning: true,
          failOnError: false,
        },
      },
    },
  ]
}

Then we need to set up a basic .eslintrc.js file. Here’s where we will have to tell ESLint to be nice to react, prettier and TypeScript.

// basic .eslintrc.js compatible with react prettier and typescript
module.exports = {
  // Specifies the ESLint parser for TypeScript
  parser: "@typescript-eslint/parser",
  extends: [
    "plugin:react/recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier/@typescript-eslint",
    "plugin:prettier/recommended",
  ],
  settings: {
    react: {
      version: "detect",
    },
  },
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  plugins: ["@typescript-eslint", "react", "prettier"],
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    // Allows for the parsing of modern ECMAScript features
    ecmaVersion: 2018,
    // Allows for the use of imports
    sourceType: "module",
  },
  rules: {
    // Disable prop-types as we use TypeScript for type checking
    "react/prop-types": "off",
    "@typescript-eslint/explicit-function-return-type": "off",
    // Enable prettier rules
    "prettier/prettier": "error",
    // interface start with capital I
    "@typescript-eslint/interface-name-prefix": "off",
    // allow "any" as type
    "@typescript-eslint/no-explicit-any": "off",
    // allow @ts-ignore for testing purposes
    "@typescript-eslint/ban-ts-ignore": "off",
  },
};

Last this we need to make sure vscode is actually working with us and understands all that we want. Install the ESLint package for vscode if you don’t have it already. A few lines on the user’s settings.json file will make it work (like we did for prettier).

// settings.json rules for ESLint
{
  "eslint.autoFixOnSave": true,
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    {
      "language": "typescript",
      "autoFix": true
    },
    {
      "language": "typescriptreact",
      "autoFix": true
    }
  ]
}

Your Gatsbyjs template with TypeScript, prettier and ESLint enabled is ready.
The initial time it costs to set it up is dwarfed by the advantages that these technologies can provide. Have fun coding!