Improve this page

"eslint" task

This task invokes the ESLint tool which reports errors about common coding problems.

When to use it

ESLint fits together with several other tools as part of Rush Stack’s recommended strategy for code validation:

  • Prettier: This tool manages trivial syntax aspects such as spaces, commas, and semicolons. Because these aspects normally don’t affect code semantics, we never bother the developer with error messages about it, nor is it part of the build. Instead, Prettier reformats the code automatically via a git commit hook (and also whenever you save a file, if you enable the editor extension).

  • TypeScript: The TypeScript compiler performs sophisticated type checking and semantic analysis that is the most important safeguard for program correctness.

  • ESLint: The lint rules supplement the compiler’s checks with additional stylistic rules that are more subjective and highly customizable. Whereas TypeScript might detect that “This function parameter is a string but was declared as a number”, the linter would detect an issue such as This class name should use PascalCase instead of camelCase. Unlike Prettier issues, fixing a lint issue may be a significant change and may even break an API contract.

  • API Extractor: This is an additional validation check for library packages only. It ensures their API contracts are well-formed and properly documented.

Although it’s recommended to set up your build system in this way, Heft doesn’t require a particular approach. Each of these components is optional, and other configurations are possible. For example, older code bases may need to use TSLint instead of ESLint.

Config files

There isn’t a Heft-specific file for this task. Heft looks for ESLint’s config file. Although ESLint supports 7 different names/formats for this file, Heft requires it to be named “.eslintrc.js”. This has a couple benefits:

  • Consistency: Using one standard name “.eslintrc.js” makes it easy to search these files, perform bulk edits, and copy configuration recipes between projects.
  • Workarounds: Using the .js file extension enables JavaScript expressions in the file. This is practice is generally discouraged because code expressions are harder to validate, and expressions can depend on environmental inputs that are invisible to caches. However, for historical reasons, ESLint’s config file format has some limitations that can only be solved with scripts (for example using __dirname to resolve file paths).

It’s not recommended to place a centralized .eslintrc.js in the monorepo root folder. This violates Rush’s principle that projects should be independent and easily movable between monorepos.

Instead, each project should have its own .eslintrc.js file. We recommend to use the @rushstack/eslint-config shared configuration, which is specifically tailored for large scale monorepos, and based on the typescript-eslint parser and ruleset. If you need additional custom lint rules, it’s recommended to create a custom NPM package that extends from @rushstack/eslint-config.

With this approach, a typical ESLint config file will have very minimal boilerplate. For example:

<project folder>/.eslintrc.js

require('@rushstack/eslint-config/patch/modern-module-resolution');

module.exports = {
  extends: [ "@rushstack/eslint-config" ],
  parserOptions: { tsconfigRootDir: __dirname }
};

NOTE: If your project uses the React framework, you should also extend from "@rushstack/eslint-config/react". See the @rushstack/eslint-config documentation for instructions.

package.json dependencies

You will need to add the eslint package to your project:

$ rush add --package eslint --dev

Alternatively, you can avoid this dependency by loading it from a “rig package”, as described in the Interfacing with Rush article. However, if you use the ESLint extension for VS Code, it will try to resolve the eslint package from your project folder. Thus it may be useful to add it to your package.json file. (The extension is also able to load a globally installed eslint package; however, its version may not match the version required by the local branch.)