Angular eslint
Introduction
Just a page to setup Eslint
Install Dependencies
ng add @angular-eslint/schematics
eslintrc.js
In the root of the project create a .eslintrc.js
/**
* -----------------------------------------------------
* NOTES ON CONFIGURATION STRUCTURE
* -----------------------------------------------------
*
* Out of the box, ESLint does not support TypeScript or HTML. Naturally those are the two
* main file types we care about in Angular projects, so we have to do a little extra work
* to configure ESLint exactly how we need to.
*
* Fortunately, ESLint gives us an "overrides" configuration option which allows us to set
* different lint tooling (parser, plugins, rules etc) for different file types, which is
* critical because our .ts files require a different parser and different rules to our
* .html (and our inline Component) templates.
*/
module.exports = {
"root": true,
// Additional projects are linted separately
"ignorePatterns": ["projects/**/*"],
"overrides": [
/**
* -----------------------------------------------------
* TYPESCRIPT FILES (COMPONENTS, SERVICES ETC) (.ts)
* -----------------------------------------------------
*/
{
"files": ["*.ts"],
"parserOptions": {
"project": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"createDefaultProgram": true
},
"extends": [
"plugin:@angular-eslint/ng-cli-compat",
/**
* NOTE:
*
* We strongly recommend using a dedicated code formatter, like Prettier, and not
* using a linter to enforce code formatting concerns.
*
* However, for maximum compatibility with how the Angular CLI has traditionally
* done things using TSLint, this code formatting related add-on config is provided.
*/
"plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
/**
* -----------------------------------------------------
* EXTRACT INLINE TEMPLATES (from within Component declarations)
* -----------------------------------------------------
*
* This extra extends is necessary to extract inline templates from within
* Component metadata, e.g.:
*
* @Component({
* template: `<h1>Hello, World!</h1>`
* })
* ...
*
* It works by extracting the template part of the file and treating it as
* if it were a full .html file, and it will therefore match the configuration
* specific for *.html above when it comes to actual rules etc.
*
* NOTE: This processor will skip a lot of work when it runs if you don't use
* inline templates in your projects currently, and when it runs on a non-Component
* file so there is no great benefit in removing it, but you can if you want to.
*/
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
/**
* Any TypeScript related rules you wish to use/reconfigure over and above the
* recommended set provided by the @angular-eslint project would go here.
*
* There are some examples below from the @angular-eslint plugin and ESLint core:
*/
"@angular-eslint/directive-selector": [
"error",
{ "type": "attribute", "prefix": "app", "style": "camelCase" }
],
"@angular-eslint/component-selector": [
"error",
{ "type": "element", "prefix": "app", "style": "kebab-case" }
]
}
},
/**
* -----------------------------------------------------
* COMPONENT TEMPLATES
* -----------------------------------------------------
*
* If you use inline templates, make sure you you have read the notes on the extends
* in the "*.ts" overrides above to understand how they relate to this configuration
* directly below.
*/
{
"files": ["*.html"],
"extends": ["plugin:@angular-eslint/template/recommended"],
"rules": {
/**
* Any template/HTML related rules you wish to use/reconfigure over and above the
* recommended set provided by the @angular-eslint project would go here.
*
* There is an example below from ESLint core (note, this specific example is not
* necessarily recommended for all projects):
*/
"max-len": ["error", { "code": 140 }]
}
}
]
}
Update ng lint command
Edit the angular.json
{
...
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
}
},
...
}
Install additional ESLint Plugins
If you want to install another plugin for ESLint, for example, to lint Jasmine spec files, install appropriate npm-package:
npm install eslint-plugin-jasmine --save-dev
We now need to add a section. Each starts with { files: } and is under the overrides section.
overrides: [
...,
{
files: ['src/**/*.spec.ts', 'src/**/*.d.ts'],
parserOptions: {
project: './src/tsconfig.spec.json',
},
// Jasmine rules
extends: ['plugin:jasmine/recommended'],
// Plugin to run Jasmine rules
plugins: ['jasmine'],
env: { jasmine: true },
// Turn off 'no-unused-vars' rule
rules: {
'@typescript-eslint/no-unused-vars': 'off'
}
}
],
Install airbnb
Install the style guide
npm install eslint-plugin-import eslint-config-airbnb-typescript --save-dev
As with the jasmine plugin add the *.ts entry under overrides
module.exports = {
...,
overrides: [
{
files: ["*.ts"],
parserOptions: {
project: [
"tsconfig.*?.json",
"e2e/tsconfig.json"
],
createDefaultProgram: true
},
extends: [
"plugin:jasmine/recommended",
// AirBnB Styleguide rules
'airbnb-typescript/base'
],
rules: {
// Custom rules
'import/no-unresolved': 'off',
'import/prefer-default-export': 'off',
'class-methods-use-this': 'off',
'lines-between-class-members': 'off',
'@typescript-eslint/unbound-method': [
'error',
{
ignoreStatic: true,
}
]
}
},
...
]
}
Configuring Prettier
To add Prettier in ESLint config, we need to install Prettier itself, plugin with Prettier rules and config that turns off all rules that conflict with Prettier:
npm i prettier eslint-config-prettier eslint-plugin-prettier --save-dev
In ESLint config "overrides" in the bottom of "extends" property in the block of rules for files with .ts extension add Prettier settings:
module.exports = {
...,
overrides: [
{
files: ["*.ts"],
parserOptions: {
project: [
"tsconfig.*?.json",
"e2e/tsconfig.json"
],
createDefaultProgram: true
},
extends: [
"plugin:@angular-eslint/recommended",
// AirBnB Styleguide rules,
'airbnb-typescript/base',
// Settings for Prettier
'prettier/@typescript-eslint',
'plugin:prettier/recommended'
],
rules: {
...
}
},
...
]
}
Configuration for Prettier should always be in the bottom of "extends" property, to turn off all the previous rules, which can conflict with Prettier.
prettier/@typescript-eslint turns off rules from @typescript-eslint, which can conflict with Prettier, and plugin:prettier/recommended does three things:
- enables eslint-plugin-prettier,
- marks prettier/prettier rules as "error",
- adds Prettier formatting rules eslint-config-prettier.
Prettier configuration
Prettier can format files with no configuration but for AirBnB code guide we need to specify some settings. Create .prettierrc.js in app root folder:
module.exports = {
trailingComma: "all",
tabWidth: 2,
semi: true,
singleQuote: true,
bracketSpacing: true,
printWidth: 100
};
This configuration will be used by ESLint and by Prettier if you want to run it separately. You can format your code with Prettier itself with prettier --write . or with Prettier Plugin for VS Code.
Configuring VS Code
VS Code can highlight errors which are found by ESLint and fix them on file save. To enable this feature install ESLint plugin for VS Code and create a file with configuration for workspace .vscode/settings.json:
"eslint.validate": [ "javascript", "typescript", "html"],
"eslint.options": {
"extensions": [".js", ".ts", "html"]
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
},
You can also install Prettier plugin for VS Code to format files with shift + option + f with Prettier.
Configuring Git Hooks
Git Hooks are scripts, which Git calls on certain events: commit, push, receive.
With Hooks we can run linting on commit creation to reduce errors falls into pull requests. For better work with Git Hooks install Husky, and to lint only staged files (it is necessary on big projects where linting can be very long) lint-staged:
npm i husky lint-staged --save-dev
Add new settings for this plugins in package.json:
"scripts": {
...,
},
"husky": {
"hooks": {
"pre-commit": "lint-staged --relative"
}
},
"lint-staged": {
"*.{js,ts}": [
"eslint --fix"
]
},
Lint-staged sends to the called command array of staged files. ng lint can't accept arrays of files and to use it we have to write an additional handler script. Or we can just run ESLint like in this example. You can use this solution for precommits, and ng lint for linting all files of project, for example, in CI pipeline.