AirBnb-based ESlint config, tweaked for my needs.
For basic usage you only need two dependencies:
pnpm add -D eslint @octetstream/eslint-config
Create an .eslintrc.json
at the root of your project and add following content:
{
"extends": "@octetstream"
}
This will import basic
config rules. Use can use other configs via submodules, like this:
{
"extends": "@octetstream/eslint-config/typescript"
}
If you use AVA
for testing, there's a config for you too.
But unlike with other configs, this does not extend any of them, so you must use it together with the others:
{
"extends": ["@octetstream/eslint-config/esm", "@octetstream/eslint-config/ava"]
}
Here's list of available configs:
/
— base config for JavaScript rules. It extends eslint-config-airbnb-base config;/esm
- extends/
config with ESM rules;/react
- extends eslint-config-airbnb config with hooks support andjsx-runtime
;/ava
- adds eslint-plugin-ava with recommemded rules. This config does not extend/
config and must be used in conjunction with other configs;/typescript
- extends/
config with recommended TypeScript ESlint rules;/typescript/esm
- extends/typescript
config with ESM rules;/typescript/react
- extends/typescript
with/react
config;/typescript/ava
- extends/ava
config with TypeScript support. Use it together with othertypescript/*
configs;/typescript/esm/react
- extends/typescript/esm
with/react
config;
This config overrides some of the rules from AitBnb config. This section contains a full list of the changed rules for each config.
This config extends eslint-config-airbnb-base
Avoid semicolon, until it's necessary.
JavaScript have specification for Automatic Semicolon Inservion, so most of the time you don't need to place a semicolon yourself. While misuse and misunderstanding may lead you to unpredictable behaviour of your scripts, both ESLint and TypeScript can help you to avoid those mistakes. So, don't waste your time writing unnecessary code.
const humber = 42
const string = "On Soviet Moon landscape see binoculars through you!"
const person = {
firstName: "Luke",
lastName: "Skywalker"
}
const number = 42;
const string = "On Soviet Moon landscape see binoculars through you!"
const person = {
firstName: "Luke",
lastName: "Skywalker"
};
If semicolon is absolutely necessary, then place it at the beginning of line, but generally you should avoid use of semicolon in your code.
const add = (a, b) => a + b
// The line starts from semicolon, because of array declaration
;["SIGTERM", "SIGINT"].forEach(signal => process.on(signal, () => { process.exitCode = 0 }))
const add = (a, b) => a + b;
["SIGTERM", "SIGINT"].forEach(signal => process.on(signal, () => { process.exitCode = 0 }))
Use camelCase for identifiers to align better with JavaScript's standard library naming convention.
const someImmutableVariable = 42
const someObject = {
someKey: "Some value"
}
function someFunction() { }
class SomeClass {
somePropery = "Some value"
someMethod() { }
}
const some_immutable_variable = 42
const some_object = {
some_key: "Some value"
}
function some_function() { }
class Some_Class {
some_propery = "Some value"
some_method() { }
}
Use double quotes by default.
const fullName = "John Doe"
const message = `Hello, ${fullName}!`
const fullName = 'John Doe'
const message = `Hello, ${fullName}!`
The code must have at most 80 symbols per line. This rule does not apply to commens, RegExp, urls, strings, and template literals.
// Try to keep names simple and code complexity low
function someFunction() {
return "some result"
}
// Comments length also ignored:
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula interdum ex imperdiet imperdiet. Integer placerat luctus dui ut blandit. Donec nunc nunc, mollis id vestibulum nec, gravida sit amet ante. Maecenas vehicula nibh dui, consectetur placerat lorem congue eu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis condimentum arcu et sapien mattis scelerisque. Pellentesque risus arcu, eleifend sed dictum at, porta at justo. Curabitur tristique justo sed odio euismod blandit. Aenean lacinia eget diam et posuere. Nulla eget placerat lectus. Quisque placerat rhoncus purus, a interdum velit facilisis ac. Donec volutpat laoreet tristique. Quisque ac commodo nibh, in ornare dolor. Etiam eros quam, aliquet eu odio non, tristique malesuada lacus. Aenean maximus risus eu finibus rutrum.
// This is still valid
const monthsRegex = /^(january|february|march|april|may|june|july|august|september|october|november|december)$/i
function thisFunctionNameIsVeryVerlyLongYouShouldNeverDoThisBecauseItsHardToReadAndBecauseThisRuleRestrictsCodeFromBeingThisLong() {
return "O_O"
}
Use 2 spaces per indent level. Never use tabs for indent and never mix tabs and spaces for indent.
Don't keep trailing commas.
const object = {
a: "a",
b: "b",
c: "c"
}
const object = {
a: "a",
b: "b",
c: "c",
}
Use const
for immutable variables and let
for mutable.
Never use var
.
const immutable = "This value is immutable"
let mutable = "This value is mutable"
mutable = "This value can be changed later in the same module"
let immutable = "This value is immutable, so use const for it"
var mutable = "This value is mutable"
mutable = "This value can be changed later in the same module"
The ++
operator is allowed to use:
let count = 1
while (count <= 10) {
console.log(count++)
}
Never use spaces inside curly braces.
import {something} from "some-package"
const object = {a: "a", b: "b"}
import { something } from "some-package"
const object = { a: "a", b: "b" }
Use consistent style for newline in objects.
Don't use parenthesis in arrow function arguments until necessary.
const showMessage = text => console.log(text)
const add = (a, b) => a + b
const showMessage = (text) => console.log(text)
Do not wrap arrow funcrtion's body in parenthesis unless necessary.
const x = a => 1 ? 2 : 3
const x = a => (1 ? 2 : 3)
Use await
in loops in needed.
import {setTimeout} from "node:timers/promises"
const intervals = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => x * 1000)
for (const ms of intervals) {
console.log(await setTimeout(ms, ms))
}
But you should remember that this can be slower.
In case if your tasks can be done concurrently, you can use Promise.all
or Promise.allSettled
for greater performance.
import {setTimeout} from "node:timers/promises"
const intervals = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => x * 1000)
const tasks = []
for (const ms of intervals) {
tasks.push(setTimeout(ms, ms))
}
console.log(await Promise.all(tasks))
The use of with statement is discouraged.
This config extends the base /
config with ES Modules support.
Always use .js
file extension for module imports.
import {something} from "./path/to/a/module.js"
This rule does not apply to packages.
import {someFunction} from "some-spackage"
import {something} from "./path/to/a/module"
The use of default and named exports are not restricted.
Allow function params reassign.
Allow methods without use of this
, because there are many cases when you don't need this
inside of class instance methods.
Allow use of void
operator.