Ir al contenido principal

Linting and formatting in Typescript

Linting and formatting tools are common in the Javascript/Typescript (JS/TS) scene, and their benefits are out of discussion: linters allows applying a set of coding style rules, whereas formatters apply a set of not coding but format style rules.

Used in a development team scenario, its usage allows unifying the codebase by applying a common set of coding and formatting rules, no matter who the coder was.

However, if not properly configured, these tools can collide in their functions, being the most common case the linter formatting code, a task that might be performed by the formatter. This article exposes the way of proceeding in order to allow both tools living in armony.

Install and configure a linter

The most common linter in the JS/TS scene is ESLint since TSLint, in the moment of writing this article, has been deprecated in favour of the first one.

To install ESLint run these commands:

$ npm install eslint --save-dev
$ npx eslint --init

Once installed you can lint your code by running a command like this:

$ npx eslint . --ext .ts --fix

Specifically this command will check recursively all the files in the current directory (eslint .) with extension .ts (--ext .ts) and will fix (--fix) all the problems found.

The above command can be created as an npm script by editing the package.json file and adding a script like this:

// package.json file
{
   // package.json configuration
   "scripts": {
      // package.json scripts
      "lint": "eslint . --ext .ts --fix"
   }
}

Regarding its configuration, the above npx eslint --init command will create a basic configuration stored in the file .eslintr, that can be customized by following the ESLint configuration guide. Due to its extension, specific ESLint configuration issues are out of the scope of this document.

To avoid ESLint parsing files that don't need being linted, an .eslintignore file can be created containing both directories and files that ESLint might ignore:

# .eslintignore example file
# Ignore bar directory
bar

# Ignore all ts files whose name started by foo
foo*.ts

Install and configure a formatter

To ensure our code follows a set of format rules, as it followed a set of style rules defined by the linter, a formatter must be used. To do it, install prettier in this way:

$ npm install --save-dev --save-exact prettier

Once installed, create an empty JSON configuration file called .prettierrc.json by running a command like this:

$ echo {} > .prettierrc.json

The specific prettier configuration options, out of the scope of this document, can be checked in the prettier documentation.

Finally create a .prettierignore file containing a list of directories whose content shouldn't be formatted, as for instance the directory containing the transpiled code or the node_modules:

# .prettierignore example file
# Ignore transpiled code stored in dist
dist

# Ignore all HTML files
*.html

Once installed, to recursivelly format all the files in the current directory, run this command:

$ npx prettier --write .

By using the --write option, the above command will modify, ie, write the format changes in the checked files. To just check the files avoiding modifying them, use the --check argument instead.

This command can also be converted into an npm script by modifying the package.json in this way:

// package.json file
{
   // package.json configuration
   "scripts": {
      // package.json scripts
      "format": "prettier --write ."
   }
}

If using Visual Studio Code, it is also possible to install the Prettier extension. It allows a more integrated way of performing code formatting at code block and file level. It also allows automatically formatting a file every time it is saved. However the Prettier extension, opposite to the Prettier module, doesn't perform operations on several files at the same time.

Allow linter and formatter work together

As said at the beginning of the article, when linters and formatters work together chances are of function overlapping.

In this specific case, to avoid ESLint formatting the code (a task that must be done by Prettier), inhibit the ESLint formatting features by installing the package eslint-config-prettier:

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

Once installed, add "prettier" to the "extends" array in the .eslintrc configuration file. Make sure to put it last, hence overriding other configs:

// .eslintrc file
{
   // .eslintrc configuration
   "extends": [
      // extends array items
      "prettier"
   ]
}

Lastly, though not necessary, a good way of ensuring that code commits are properly linted and formatted is creating an npm script that combines both functions:

// package.json file
{
   // package.json configuration
   "scripts": {
      // package.json scripts
      "lint": "eslint . --ext .ts --fix",
      "format": "prettier --write .",
      "pre-commit": "npm run lint && npm run format"
   }
}

In the above example, a pre-commit script is added to the already existing npm scripts combining two of them (lint and format) in a new one that will lint and then format our project code.

This script could also include other steps, as building (npm run build) and testing (npm run test), to ensure our code is properly linted, formatted, built and tested before commiting it.

Finally, a git pre-commit hook could be created to run it automatically before every commit, ensuring that the code pushed to our repository follows a set of style and format rules, properly builds and passes tests, all done automatically.

Comentarios

Entradas populares de este blog

Linting C# in Visual Studio Code

Though very usual in programming environments as Javascript/Typescript, linting , or analyzing code for enforcing a set of coding style rules, is not usually present in the .NET based environments. Rule enforcing is really useful when working on team shared codebases in order to keep them coherent, what in last term reduces both development times and coding errors. A linting example Maybe a practical example would be helpful for explaining what  linting  is to the newcomers (feel free to go on if you aren't). Let's imagine you are a new member in a C# development team that has well established set of coding style rules. Instead (or apart) of putting them in a document, they've adopted a tool that checks these rules during the code building process. Your first code is such ambitious as this: namespace HelloWorld {      using System;      public class Program      {           public static void Main(string[] args)           {                Console

ESlint: Ignore unused underscore variables

Some naming conventions promote the use of the underscore character (" _ ") for those variables that must be declared but are not being used. One common case is that in which a function signature contains some variables that will not be used, as for instance the Express error handlers: app.use(function(err, req, res, next) { console.error(err.stack); res.status(500).send('Something broke!'); }); In the above example only the arguments err and res are being used, though all four must be defined in the handler signature. Thus, following the naming convention of using underscores for those unused variables, we could recode it as: app.use(function(err, _, res, __) { console.error(err.stack); res.status(500).send('Something broke!'); }); Though it makes the function more readable, it comes with a problem if using ESlint: it will blame by declaring unused variables. error '_' is defined but never used error '__' is define

Using Bitbucket app passwords with git on MacOS (OSX)

Learn how Bitbucket passwords are stored by git on MacOS.