Linting in TypeScript using ESLint and Prettier

As developers, we typically start a project by adding configuration and scripts for linting, then formatting and type-checking the codebase syntax and style.

This process is even more important when working in a team, as everyone needs to be consistent in codebase syntax and style. Additionally, to ensure that our application is free of typos or bugs when it comes to production, we should type-check our code along the way.

Having formatting tools, linting tools, and TypeScript can help us automate this process.

In this article, we'll use ESLint and TypeScript, and we'll also see how to add Prettier and other tools to automate this process.

NOTE: There are compatibility issues with certain versions of Node and the latest versions of ESLint and Prettier, How to Fix ntoskrnl.exe BSOD Error on Windows 11 (8 Best Methods) So while following the code section behind, make sure you run Node version >= 16.0.0.

Compile TypeScript code

Typescript is a superset of JavaScript that helps us perform static type checking at compile time. TypeScript will provide you with a better development experience thanks to the autocomplete feature in the editor. TypeScript also helps you maintain code in large code bases.

First, we need a compiler to convert the TypeScript code into JavaScript so that the browser can read it. Let's install the dependencies using your favorite package manager. Go to the appropriate folder on your computer and run one of the following commands in Terminal:

#npm
npm install --save-dev typescript
#yarn
yarn add typescript --dev 

After installation, you will see a new entry devDependencies properties in your package.json file as:

{
  "name": "Linting TypeScript with ESLint",
  "version": "1.0.0",
  "devDependencies": {
    "typescript": "^4.9.4"
  }
}

If you want to verify that it is installed, you can run the following command to check the version:

npx tsc --version
# Version 4.4.3

In your folder How to Fix YouTube Audio Renderer Error (9 Ways) create an index.ts file in the src directory and add the following TypeScript code:

// src/index.ts
const favoriteFruits: string[] = ["apple", "strawberry", "orange"];
function addFruit(fruit: string) {
  favoriteFruits.push(fruit);
}

We can compile TypeScript code to JavaScript by running the following command in the terminal:

npx tsc src/index.ts

Afterwards, we will see a newly generated JavaScript file in the same directory as the TypeScript file:

// src/index.js
var favoriteFruits = ["apple", "strawberry", "orange"];
function addFruit(fruit) {
    favoriteFruits.push(fruit);
}

By default, the compiler will create a JavaScript file side by side with the TypeScript source file from which it was created. This is not a good idea as you end up mixing the build results with the source code.

So let's change some default compiler settings, starting with where we want to place the compiled code, the JavaScript level we want to convert (default: ECMAScript 3) and the files we want to compile.

There are two ways to create TypeScript compiler settings:

  1. Run the following command in the terminal: npx ts``c --init. This will generate a default TypeScript configuration file

  2. Create a file called tsconfig.json in the root of the project and contain your settings

In this example, I'll create the TypeScript compiler settings manually. However, I encourage you to choose the first option. It will create a configuration file with some recommended options - all described with comments explaining what they do.

You can modify these settings as needed. To see a complete list of supported compiler options, you can check out the TypeScript Playground:

// tsconfig.json
{
  "compilerOptions": {
    "outDir": "dist", // where to put the compiled JS files
    "target": "ES2020", // which level of JS support to target
    "module": "CommonJS", // which system for the program AMD, UMD, System, CommonJS
    // Recommended: Compiler complains about expressions implicitly typed as 'any'
    "noImplicitAny": true, 
  },
  "include": ["src"], // which files to compile
  "exclude": ["node_modules"], // which files to skip
}

Congratulations! Now you can start writing TypeScript and compiling it to JavaScript by running npx tsc.

You can include the above commands in a script to make it easier to run. Go to package.json and add the --watch flag to watch the file for changes. Remember, everything described in compilerOptions can be passed to the command line using CLI flags:

// package.json
{
  "name": "Linting TypeScript with ESLint",
  "version": "1.0.0",
  "devDependencies": {
    "typescript": "^4.9.4"
  },
  "scripts": {
    "dev": "tsc --watch"
  }
}

What is ESLint?

One of the most popular linting tools is ESLint, Fun Notes - Share valuable tutorials! It will analyze your code to find potential errors and improve code quality by defining coding conventions and then automatically enforcing them. Let's see how to install ESLint into our TypeScript project.

First, install the following dependencies to your devDependencies:

npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
  • eslint: ESLint core library

  • @typescript-eslint/parser: A parser that allows ESLint to understand TypeScript code

  • @typescript-eslint/eslint-plugin: Plugin with a set of recommended TypeScript rules

Similar to the Typescript compiler settings, you can generate a configuration file using the command line --init tags from ESLint or create it manually. Either way, you must have an ESLint configuration file.

Let's create a configuration file using the CLI. Run the following command in the terminal:

npx eslint --init

Next, you'll see a series of questions that allow you to adjust the profile to your liking:

  • How do you want to use ESLint?

  • What type of modules does your project use?

  • Which framework do you use for your project?

  • Does your project use TypeScript?

  • Where does your code run?

  • How would you like to define the style for your project?

Depending on the options selected, the ESLint CLI will create a .eslintrc.json configuration file in the project root directory with some default settings. You can override certain options in the configuration file if you already have settings you like.

complete list. Available ESLint settings You can also browse configuration files

Linting with ESLint

For this article, replace the default settings in the configuration file with:

// .eslintrc
{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 12,
    "sourceType": "module"
  },
  "plugins": ["@typescript-eslint"],
  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
  "rules": {

  },
  "env": {
    "browser": true,
    "es2021": true
  },
}
  • parser: This specifies the parser that ESLint uses when analyzing the code

  • parserOptions: Specify which JS language options you want to support, such as the ECMAScript syntax version you want to use

  • plugins: This is where you define the plugins you want to use

  • extends: tells ESLint to set the extended configuration. The order is important because the last extension option will override previous options in any conflicting configurations.

  • env: the environment your code will run in

When we add an ESLint rule, it is overwritten in the extends list. Let's add some rules to see how it works:

// .eslintrc
{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 12,
    "sourceType": "module",
  },
  "plugins": ["@typescript-eslint"],
  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],

  "rules": {
    "@typescript-eslint/no-unused-vars": "error",
    // to enforce using type for object type definitions, can be type or interface 
    "@typescript-eslint/consistent-type-definitions": ["error", "type"], 
  },

  "env": {
    "browser": true,
    "es2021": true
  }
}

In short, the first rule we apply is assigned a value error, but error is not the only value we can assign - we have three options:

  • off or 0: completely close the rule

  • warn or 1: treat the rule as a warning but will not fail when running the linter

  • error or 2: Treat the rule as an error. Fails when running linter

Note: In some ESLint rules, such as the second rule, you need to set additional options to use array literal syntax.

You can tell ESLint to lint your code using: eslint --ext .js,.ts. The extflag specifies which file extensions ESLint should consider when searching for files in the target directory. In this case, we include the TypeScript file extension: .ts (by default, it is .js)

Now you can add a lint script to your package.json using the above command:

// package.json
{
  "name": "Linting TypeScript with ESLint",
  "version": "1.0.0",
  "scripts": {
    "dev": "tsc --watch",
    "lint": "eslint --ext .js,.ts .",
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^5.45.1",
    "@typescript-eslint/parser": "^5.45.1",
    "eslint": "^8.29.0",
    "typescript": "^4.9.4"
  }
}

You'll find that some files don't need to be checked at all, like your dist folder, so you can prevent linting by creating a .eslintignore file and add the folders or files you want to ignore:

node_modules
dist

This is usually related to the contents of your .gitignore file, so to have a single source of truth you can update your lint script to use the --ignore-path flag:

// package.json
{
  // ...
  "scripts": {
    "lint": "eslint --ignore-path .eslintignore --ext .js,.ts ."
   },
  // ...
}

Now you're ready to go! I recommend integrating ESLint into any editor you use. If it's VSCode, go to extensions and install the ESLint extension.

Once you install and enable it, you will see errors as they appear in your code without running the redline-underlined script.

NOTE: You will see ESLint error messages printed inline in the editor; extension here is another one called Error Lens, which highlights the entire line and displays the error message immediately, rather than hovering with the pointer to view it:

Another feature of ESLint is that it can automatically fix code Quick fix when you hover and right click, or you can hit command and +:

It can be tedious to manually fix all the rule-breaking errors, but you can run the following command to tell ESLint to fix what it can:

npm run lint -- --fix

Tip: You can pass parameters using double dashes - for npm scripts, it will be received as an argument to the script npm executes:

npm run <command> [-- <args>]

What is more beautiful?

Prettier is a well-known code formatter that supports many different programming languages. It can automatically format code according to specified code styles, thus helping us avoid manual formatting of code.

Nowadays, it is very common to use ESLint and Prettier together, we will learn how to integrate Prettier with ESLint. First, let’s look at the differences between the two and why they can benefit together.

Why do we need Prettier and ESLint?

The main function of a linter is to improve your code by analyzing it and alerting you to any potential issues based on a customizable or predefined set of rules. These rule sets, or rules, allow development teams to maintain a consistent coding style and identify potential errors caused by inconsistent coding styles.

Code formatters like Prettier, on the other hand, ensure consistent style by parsing the code and reprinting it according to its rules. For example, you can specify that all JavaScript statements must end with a semicolon; the code formatter automatically adds a semicolon to any statement that does not have a semicolon.

Essentially, you use ESLint to specify the set of rules that must be followed, and then use Prettier to fix situations in your code where those rule sets are broken.

Integration is more beautiful

With that done, let's add Prettier to our project; run the following command in the terminal:

npm install --save-dev prettier

Compared to ESLint, Prettier requires no configuration files, which means you can run and use it right away. However, if you want to set up a configuration, you need to create a file called .prettierrc (in the root of your project) where you can define formatting options.

You can check out the full list of formatting options to try out in the Prettier Playground:

// .prettierrc
{
  "semi": false, // Specify if you want to print semicolons at the end of statements
  "singleQuote": true, // If you want to use single quotes
  "arrowParens": "avoid", // Include parenthesis around a sole arrow function parameter
}

Next, we'll start using Prettier on the command line to format our code:

npx prettier --write src/index.ts
# src/index.ts 37ms

I added a write flag to overwrite the TypeScript file, otherwise, it won't overwrite it and will just log the formatting code in the CLI.

Let's add the Prettier command to our script, just like we did for TypeScript and ESLint. We also support all files ending in .ts, .js, and .json and ignore the same files and directories with gitignore (or you can create a .prettierignore file):

// package.json

{
  // ...
  "scripts": {
    "dev": "tsc --watch",
    "lint": "eslint --ext .js,.ts .",
    "format": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\""
  },
  // ...
}

Now you can run npm run format command to format and fix all your code. But what if we want to format the code immediately after saving the file?

That's possible! In VSCode, go to the extensions tab, look for the Prettier extension, and make sure it is enabled. After enabling it, we need to configure some things in VSCode.

You can open the Command Palette (Command + Shift + P) and look for Preferences: Open Settings (JSON). Then you need to change the editor default formatter and add additional configuration to format the code when saving the file:

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

Avoid conflicts when using ESLint and Prettier

You may encounter problems when Prettier and ESLint rules overlap. You can try to auto-format the code, but it will show some conflicts with ESLint.

The best solution here is to use the plugin eslint-config-prettier to disable all code-formatting-independent ESLint rules, since Prettier is already good at that:

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

Once installed, let's go into the .eslintrc file and prettier any other previous rules that disable other plugins at the end of the extension list:

// .eslintrc
{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": 12,
    "sourceType": "module",
  },
  "plugins": ["@typescript-eslint"],
  // HERE
  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
  "rules": {
    "@typescript-eslint/no-unused-vars": "error",
    "@typescript-eslint/consistent-type-definitions": ["error", "type"],
  },
  "env": {
    "browser": true,
    "es2021": true
  }
}

That's it! Now you know how to use these static testing tools effectively. It would be great to have some automation for specific tasks like linting, formatting, and type checking.

in conclusion

Using TypeScript and ESLint together can increase your confidence in your code. It helps us prevent mistakes and saves us time in the long run. I recommend trying TypeScript and ESLint to give you and your whole team a better development experience the next time you build something cool.

Guess you like

Origin blog.csdn.net/weixin_47967031/article/details/132864849