eslint-config-styleguidejs
Version:
JS Style Guide ESLint Configuration
249 lines (179 loc) • 8.6 kB
Markdown
# ESLint Configuration Best Practices
This document explains how our ESLint configuration aligns with modern JavaScript and TypeScript best practices.
## Core Principles
Our ESLint configuration is built around several core principles that reflect modern JavaScript and TypeScript development:
1. **Type Safety**: Leveraging TypeScript's static type system to catch errors at compile time
2. **Modern Syntax**: Encouraging ES6+ features and patterns
3. **Readability**: Prioritizing code that is easy to read and understand
4. **Consistency**: Enforcing consistent style and patterns across the codebase
5. **Maintainability**: Avoiding patterns that make code difficult to maintain or refactor
## Psychological Benefits of Our Spacing Rules
Our configuration enforces no spaces inside object literals and array brackets. This approach offers several cognitive and psychological benefits:
### Visual Cohesion
```js
// Without spaces - objects and arrays are perceived as cohesive units
const user = {name: 'John', age: 30};
const points = [10, 20, 30];
// With spaces - creates visual fragmentation
const user = { name: 'John', age: 30 };
const points = [ 10, 20, 30 ];
```
When brackets and braces are treated as part of the data structure they contain (without spaces), the brain processes them as a single cohesive unit. This reduces cognitive load by treating objects and arrays as atomic entities rather than collections of separate elements.
### Alignment with Syntax Structures
```js
// Consistent treatment of all bracket types
function process({id, name}) { // object destructuring
return [id, name]; // array literal
}
// Inconsistent visual treatment
function process({ id, name }) {
return [ id, name ];
}
```
Our no-space approach creates visual consistency with other bracket-like structures in JavaScript (function calls, control structures), strengthening the mental model of how code is structured.
### Reduced Visual Noise
```js
// Less visual noise - easier to scan
const config = {
user: {name: 'John', role: 'admin'},
settings: {theme: 'dark', notifications: {email: true, push: false}}
};
// More visual noise - harder to scan
const config = {
user: { name: 'John', role: 'admin' },
settings: { theme: 'dark', notifications: { email: true, push: false } }
};
```
Each space adds visual noise to the code. With nested structures, this noise compounds quickly, making it harder for the brain to filter out irrelevant information and focus on the content.
### Muscle Memory and Typing Efficiency
Consistently typing without spaces between brackets builds muscle memory, making coding more fluid and reducing the cognitive overhead of style decisions. This consistency extends to IDEs and code formatters, creating a seamless experience across tools.
### Psychological Anchoring
The absence of spaces creates stronger "anchoring points" for the eyes when scanning code. The brain can quickly identify the boundaries of data structures without having to process extra whitespace, making code navigation more efficient.
## Key Best Practices
### Modern JavaScript Features
```js
// Prefer const for variables that aren't reassigned
const user = {name: 'John'}; // ✅
let user = {name: 'John'}; // ❌ unless reassigned
// Use arrow functions for cleaner syntax and lexical this
const getName = () => user.name; // ✅
function getName() { return user.name; } // ❌ unless needed for specific reasons
// Use template literals for string concatenation
const greeting = `Hello, ${user.name}!`; // ✅
const greeting = 'Hello, ' + user.name + '!'; // ❌
```
Rules enforcing these practices:
- `prefer-const`: Encourages using `const` for variables that aren't reassigned
- `prefer-arrow-callback`: Promotes arrow functions over function expressions
- `prefer-template`: Encourages template literals over string concatenation
- `no-var`: Prevents using the outdated `var` keyword
### Object and Array Handling
```js
// Use object shorthand
const name = 'John';
const user = {name}; // ✅
const user = {name: name}; // ❌
// Use object destructuring
const {name, age} = user; // ✅
const name = user.name; const age = user.age; // ❌
// Use spread for object copying
const userCopy = {...user}; // ✅
const userCopy = Object.assign({}, user); // ❌
```
Rules enforcing these practices:
- `object-shorthand`: Encourages object property shorthand
- `prefer-destructuring`: Promotes destructuring for objects and arrays
- `no-restricted-properties`: Discourages `Object.assign` in favor of spread syntax
### Error Prevention
```js
// Use strict equality checks
if (value === null) {} // ✅
if (value == null) {} // ❌
// Avoid unintentional type coercion
const sum = 1 + Number(value); // ✅
const sum = 1 + +value; // ❌
```
Rules enforcing these practices:
- `eqeqeq`: Requires strict equality operators (`===` and `!==`)
- `no-implicit-coercion`: Prevents shorthand type conversions
- `no-unused-vars`: Catches variables that are declared but never used
### TypeScript Best Practices
```ts
// Use explicit return types for functions
function getData(): Promise<Data> {} // ✅
function getData() {} // ❌ for public APIs
// Consistent type assertions
const user = data as User; // ✅
const user = <User>data; // ❌
// Proper spacing in type annotations
const name: string = 'John'; // ✅
const name : string = 'John'; // ❌
```
Rules enforcing these practices:
- `@typescript-eslint/consistent-type-assertions`: Enforces consistent type assertion style
- `@typescript-eslint/naming-convention`: Ensures consistent naming for different types of symbols
- `@stylistic/type-annotation-spacing`: Enforces consistent spacing in type annotations
### Module System
```js
// Organized imports
import React, {useState} from 'react';
import {debounce} from 'lodash';
import {User} from './types';
import {fetchUser} from './api';
// Explicit file extensions
import {Button} from './components/Button.js';
import styles from './styles.css';
```
Rules enforcing these practices:
- `import/order`: Groups and sorts import statements
- `import/no-cycle`: Prevents circular dependencies
- `import/extensions`: Requires file extensions for certain file types
### Code Style and Formatting
```js
// Consistent spacing
function add(a, b) { // ✅
function add( a,b ){} // ❌
// Consistent quotes
const name = 'John'; // ✅
const name = "John"; // ❌
// Consistent semicolons
const value = 42; // ✅
const value = 42 // ❌
// No spaces inside object literals
const user = {name: 'John'}; // ✅
const user = { name: 'John' }; // ❌
// No spaces inside array brackets
const items = [1, 2, 3]; // ✅
const items = [ 1, 2, 3 ]; // ❌
```
Rules enforcing these practices:
- `indent`: Ensures consistent indentation (2 spaces)
- `quotes`: Enforces single quotes for strings
- `semi`: Requires semicolons at the end of statements
- `object-curly-spacing`: No spaces inside object literals
- `array-bracket-spacing`: No spaces inside array brackets
## React Best Practices
```jsx
// Functional components
const Button = ({onClick, children}) => ( // ✅
<button onClick={onClick}>{children}</button>
);
// Hooks dependencies
useEffect(() => {
fetchData(userId);
}, [userId]); // ✅ including all dependencies
```
Rules enforcing these practices:
- `react/jsx-uses-react`: Optimizes for the new JSX transform
- `react/react-in-jsx-scope`: Allows omitting React import with new JSX transform
- `react-hooks/rules-of-hooks`: Enforces Rules of Hooks
- `react-hooks/exhaustive-deps`: Ensures all dependencies are properly declared
## Benefits of These Practices
1. **Improved Code Quality**: Catching potential bugs and anti-patterns early
2. **Enhanced Developer Experience**: Consistent codebase is easier to work with
3. **Better Performance**: Encouraging patterns that align with JavaScript engine optimizations
4. **Future-Proofing**: Aligning with the direction of JavaScript and TypeScript evolution
5. **Team Efficiency**: Reducing time spent on code reviews for style and formatting issues
## Conclusion
Our ESLint configuration is designed to enforce modern best practices while maintaining a balance between strictness and flexibility. The rules are carefully chosen to encourage patterns that lead to more maintainable, readable, and robust code, while avoiding unnecessary restrictions that might impede development velocity.
By following these practices, we ensure our codebase remains high-quality, consistent, and aligned with the evolving JavaScript and TypeScript ecosystems.