Setting up TypeScript with ESLint & Prettier from Scratch

on

In my previous tutorial, we created a Node.js project with ESLint and Prettier from scratch. In this tutorial, we are going to do the same, but we’ll setup our development environment for using TypeScript, instead of JavaScript.

TypeScript is a superset of JavaScript developed by Microsoft that adds optional static typing to JavaScript. TypeScript is safer than JavaScript because it can automatically verify that our code is free of type errors. Furthermore, it is more convenient to work with, since it enables code autocompletion in most IDEs.

Installing NVM

Just like my previous tutorial, we’ll start by installing Node Version Manager (NVM). Since it’s rare that all of our projects will require the same Node.js version, it is not practical to have a global Node.js installation, so we’ll use NVM for managing our installations and to automatically switch to the correct version as required.

NVM can be installed by downloading and running the latest installation script in NVM’s documentation.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash

You will probably get a message saying to close and reopen your terminal, so make sure to do that. Then install Node v20.7.0.

nvm install 20.7.0

Add the Node version to .nvmrc.

echo "20.7.0" > .nvmrc
nvm use
Now using node v20.7.0 (npm v10.1.0)

Installing TypeScript

First, we should initialize npm.

npm init

You will be asked a few questions about your project (just press Enter to accept the defaults) and npm will create a package.json.

We can now install TypeScript as a development dependency.

npm install typescript --save-dev

TypeScript needs to be transpiled to JavaScript before we can run our program in Node.js. But we have to configure the TypeScript compiler.

Run the command below to create a new TypeScript configuration file tsconfig.json in your project’s root directory. Npx is npm’s package runner - it will try to find a package locally, or alternatively download it from npm, and then run it.

npx tsc --init

There are many tsconfig properties, which are explained in detail in TypeScript’s documentation. For this tutorial, we’ll use the configuration below:

{
  "compilerOptions": {
    "target": "es2022",
    "module": "commonjs",
    "outDir": "dist",
  },
  "include": ["src"],
  "exclude": ["node_modules"],
}
  • target: The ECMAScript version to transpile TypeScript to. It should be compatible with our Node.js version, for example, Node v20 supports ES2022 features.
  • module: Sets the module system for the transpiled code. We’ll be using commonjs, but you could also try nodenext, as recent versions of Node fully support ECMAScript modules.
  • outDir: Output directory for JavaScript code.
  • include: Location of our TypeScript source files.
  • exclude: Paths to exclude from processing.

Running npx tsc will read the tsconfig.json configuration and transpile TypeScript to JavaScript. We can add our build command to package.json.

{
  ...
  "scripts": {
    "build": "npx tsc"
  },
  ...
}

Installing ESLint

Install ESLint and the TypeScript parser/plugin from npm.

npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
  • eslint: The ESLint library.
  • @typescript-eslint/parser: ESLint parser for converting TypeScript to ESLint-compatible code.
  • @typescript-eslint/eslint-plugin: Set of recommended TypeScript rules for the linter.

Before using ESLint we need to create a configuration file. Running the command below will ask you some questions and create the file for you.

npm init @eslint/config

Choose the following answers:

✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · commonjs
✔ Which framework does your project use? · none
✔ Does your project use TypeScript? · Yes
✔ Where does your code run? · node
✔ What format do you want your config file to be in? · JSON
The config that you've selected requires the following dependencies:

@typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
✔ Would you like to install them now? · No

Then modify .eslintrc.json.

{
  "root": true,
  "env": {
    "es2022": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "plugins": [
    "@typescript-eslint"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 2022
  },
  "ignorePatterns": [
    "node_modules/",
    "dist/"
  ],
  "rules": {}
}
  • root: Only use the .eslintrc.json in the current directory. By default ESLint will also search in parent directories, all the way up to root /, and merge any configuration files it finds.
  • env: Provides global variables for the defined environments.
  • extends: Extends our base configuration file with rules from other files.
  • plugins: The plugins we are using to extend our base configuration.
  • parser: Custom parser to convert our code into ESLint compatible code.
  • parserOptions: Defines the ECMAScript version syntax to be supported by the linter.
  • ignorePatterns: Paths the linter should ignore.
  • rules: Our custom linter rules, which override the defaults.

Installing Prettier

ESLint checks our code for syntax and style errors, but we have to fix any issues it finds manually. To automatically format our code to conform to our styling rules, we can use Prettier.

npm install prettier --save-dev

Since some ESLint styling rules might conflict with Prettier, we disable them with eslint-config-prettier.

npm install eslint-config-prettier --save-dev

We also need to modify .eslintrc.json and add the prettier rule overrides as the last entry in the ESLint extensions list.

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

Prettier already has some built-in rules. To override the preset rules, we have the option to create a custom configuration file.

Setting up ESLint and Prettier in VS Code

To use ESLint and Prettier in VS Code we need to install their respective VS Code extensions. Switch to the extensions tab, then find and install ESLint and Prettier.

VS Code - ESLint

VS Code - Prettier

VS Code has several built-in code formatters, so we need to select the one we want to use.

Go to FilePreferencesSettings and type formatter in the search box. Switch to the Workspace tab (instead of User) and select Prettier as the Default Formatter from the drop-down list. Also, tick the Format On Save checkbox.

VS Code settings

VS Code should create a .vscode directory with custom settings that apply only to this project. We can open .vscode/settings.json to view the local settings.

{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true
}

Create an app

Let’s create a simple application to test the TypeScript compiler.

This is the directory structure of our project:

.
└─dist
└─src
│ ├─app.ts
│ └─MyClass.ts
└─.eslintrc.json
└─package.json
└─tsconfig.json

In the src directory, create a file MyClass.ts.

export class MyClass {
  name: string;

  constructor(name: string) {
    this.name = name;
  }

  getMessage(): string {
    return `Hello ${this.name}`;
  }
}

In the same directory, also create app.ts.

import { MyClass } from "./MyClass";

const myInstance = new MyClass("world");

console.log(myInstance.getMessage());

Run the TypeScript compiler.

npm run build

The TypeScript compiler should transpile our code to JavaScript in the dist directory. We can confirm by opening dist/app.js.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const MyClass_1 = require("./MyClass");
const myInstance = new MyClass_1.MyClass("world");
console.log(myInstance.getMessage());

Also, let’s confirm that our linter works. Create a variable that is not used anywhere in the code and ESLint should immediately complain.

ESLint error

We can run our app with node dist/app.js. Add the command to package.json.

{
  ...
  "scripts": {
    "build": "npx tsc",
    "start": "node dist/app.js"
  },
  ...
}

Finally, run our app.

npm start
Hello world

Happy coding!