An open API service indexing awesome lists of open source software.

https://github.com/noneforge/eslint-config

TypeScript/JavaScript ESLint configuration with strict type checking and modern stylistic rules
https://github.com/noneforge/eslint-config

code-quality code-style eslint eslint-config eslint9 eslintconfig flat-config javascript javascript-eslint lint noneforge stylistic type-checking typescript typescript-eslint

Last synced: about 1 month ago
JSON representation

TypeScript/JavaScript ESLint configuration with strict type checking and modern stylistic rules

Awesome Lists containing this project

README

          

# @noneforge/eslint-config

Modern TypeScript/JavaScript ESLint configuration with strict type checking and comprehensive stylistic rules. Built for ESLint 9+ flat config with full TypeScript 5.5+ support.

## Features

- โœจ **ESLint 9 Flat Config** - Modern configuration format with better performance
- ๐ŸŽฏ **Strict Type Checking** - Comprehensive type-aware rules to catch errors at build time
- ๐ŸŽจ **Built-in Formatting** - Replaces Prettier with @stylistic/eslint-plugin for unified tooling
- ๐Ÿš€ **TypeScript 5.5+ Support** - Leverages latest TypeScript features and optimizations
- ๐Ÿ“ฆ **Zero Config Philosophy** - Sensible defaults that work out of the box
- โšก **Performance Optimized** - Uses `projectService` for faster type checking
- ๐Ÿ”ง **Smart File Detection** - Different rules for tests, configs, and type definitions

## Related Packages

- [@noneforge/eslint-config-node](https://www.npmjs.com/package/@noneforge/eslint-config-node) - Node.js backend configuration
- [@noneforge/eslint-config-angular](https://www.npmjs.com/package/@noneforge/eslint-config-angular) - Angular application configuration

## Requirements

- Node.js >=18.18.0
- ESLint >=9.22.0
- TypeScript >=5.5.0

## Installation

```bash
npm install --save-dev @noneforge/eslint-config eslint typescript
```

or with Yarn:

```bash
yarn add --dev @noneforge/eslint-config eslint typescript
```

## Usage

Create an `eslint.config.js` file in your project root:

```javascript
import config from '@noneforge/eslint-config';

export default [
...config,
// Your custom rules here
];
```

### With Custom Rules

```javascript
import config from '@noneforge/eslint-config';

export default [
...config,
{
rules: {
// Override or add custom rules
'no-console': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
}
}
];
```

### For Monorepos

```javascript
import config from '@noneforge/eslint-config';

export default [
...config,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
project: ['./packages/*/tsconfig.json'],
}
}
}
];
```

## Rule Categories

### ๐Ÿ›ก๏ธ Core JavaScript Error Prevention
**Essential rules to catch common JavaScript errors:**
- **Syntax and Logic Errors**: `no-dupe-keys`, `no-unreachable`, `no-unsafe-negation`
- **Variable Issues**: `no-undef`, `no-unused-vars` (TypeScript uses `@typescript-eslint/no-unused-vars` with enhanced options), `no-redeclare`
- **Async/Control Flow**: `no-async-promise-executor`, `no-await-in-loop`, `for-direction`
- **Regex Safety**: `no-control-regex`, `no-invalid-regexp`, `no-regex-spaces`

**Enhanced unused variables detection:**
- Variables/args starting with `_` are ignored
- Rest siblings in destructuring are ignored (`const { used, ...rest } = obj`)
- Only checks function arguments after the last used one
- Destructured array elements starting with `_` are ignored

### ๐ŸŽฏ TypeScript Type Safety
**Strict type checking for maximum safety:**
- **No Any Policy**: `@typescript-eslint/no-explicit-any`, all `no-unsafe-*` rules
- **Type Assertions**: Enforces consistent assertions, prevents unnecessary type operations
- **Nullish Handling**: `strict-boolean-expressions` with smart nullable object support
- **Promise/Async**: `no-floating-promises`, `no-misused-promises`, `promise-function-async`
- **Type Definitions**: `consistent-type-definitions` is disabled - choose `type` or `interface` based on your needs:
- Use `interface` for: object shapes that can be extended, implements clauses, public APIs
- Use `type` for: unions, intersections, mapped types, tuple types
- Consider `interface extends` over `type &` for better performance

```typescript
// โŒ Strict boolean expressions prevent errors
if (count) { } // Error: number coercion
if (text) { } // Error: string coercion

// โœ… Be explicit
if (count > 0) { }
if (text !== '') { }
if (user) { } // OK: nullable object check
```

### ๐Ÿ“ฆ Import/Export Management
**Automatic import organization:**
- **Sorting**: `simple-import-sort` for consistent ordering
- **Type Imports**: Enforces inline type imports (`import { type User }`)
- **No Side Effects**: Prevents `import type` with side effects
- **Module System**: No `require()` in TypeScript, ESM preferred

```typescript
// โœ… Auto-sorted and organized
import { type Config } from './config';
import { type User, type Product } from '@/types';
import { useState } from 'react';
import path from 'node:path';
```

### ๐ŸŽจ Code Formatting (Prettier Replacement)
**Built-in formatting via @stylistic/eslint-plugin:**
- **Indentation**: 2 spaces, with detailed alignment rules
- **Quotes**: Single quotes with escape avoidance
- **Semicolons**: Always required
- **Line Length**: 120 chars (ignores URLs, strings, templates)
- **Spacing**: Comprehensive rules for consistency

### ๐Ÿ—๏ธ Code Quality & Best Practices
**Modern JavaScript/TypeScript patterns:**
- **ES6+ Features**: `prefer-const`, `no-var`, `prefer-spread`, `prefer-object-has-own`
- **Logical Operators**: `logical-assignment-operators` (use `??=`, `&&=`, `||=`)
- **String Methods**: `prefer-string-starts-ends-with` over regex/indexOf
- **Array Methods**: `prefer-find` over filter[0], `prefer-includes` over indexOf
- **Optional Chaining**: `prefer-optional-chain` over && chains

```typescript
// โŒ Old patterns
const first = array.filter(x => x.id === id)[0];
if (text.indexOf('prefix') === 0) { }
const value = obj && obj.nested && obj.nested.value;

// โœ… Modern patterns
const first = array.find(x => x.id === id);
if (text.startsWith('prefix')) { }
const value = obj?.nested?.value;
```

### ๐Ÿ“ Naming Conventions
**Consistent naming across the codebase:**
- **Variables**: `camelCase`, `PascalCase`, or `UPPER_CASE`
- **Functions**: `camelCase` or `PascalCase`
- **Types/Interfaces**: `PascalCase`
- **Enums**: `PascalCase`
- **Type Parameters**: `PascalCase` (generics)

### ๐Ÿ”„ Async/Promise Rules
**Comprehensive async code handling:**
- **Floating Promises**: Must be awaited or explicitly voided
- **Async Functions**: Must return promises (`promise-function-async`)
- **Await Usage**: `require-await` ensures async functions use await
- **Return Await**: Required in try-catch blocks for proper stack traces

```typescript
// โŒ Common async mistakes
async function bad() {
fetchData(); // floating promise
return await promise; // unnecessary outside try-catch
}

// โœ… Proper async handling
async function good() {
await fetchData(); // or void fetchData();
try {
return await promise; // correct in try-catch
} catch (e) {
// handle error
}
}
```

### ๐Ÿ“š JSDoc Documentation
**Smart documentation requirements:**
- **Exported Elements Only**: JSDoc required only for explicitly exported interfaces, types, enums, functions, and arrow functions
- **Library Files**: Stricter requirements for files in `lib/` directories and `public-api.ts` - all public classes, methods, and functions must be documented
- **Alignment**: Enforces consistent JSDoc formatting
- **TypeScript Integration**: Disables type annotations in JSDoc
- **Flexible for Internal Code**: No JSDoc required for non-exported code, keeping internal implementation clean

### ๐Ÿงช Test File Rules
**Relaxed rules for test files (`*.spec.ts`, `*.test.ts`):**
- `any` type allowed for test flexibility
- No JSDoc requirements
- Console statements permitted
- Higher callback nesting limit (10 levels)
- Magic numbers allowed
- **No indentation enforcement** (`@stylistic/indent: 'off'`) - flexible formatting for test readability
- **No line length limits** (`@stylistic/max-len: 'off'`) - allows long test descriptions and assertions
- **Floating promises allowed** (`@typescript-eslint/no-floating-promises: 'off'`) - simplified async test scenarios

### ๐Ÿ“ Special File Handling
**Smart detection for different file types:**
- **Config Files** (`*.config.js/ts`): Allows `require()`, relaxed return types
- **Declaration Files** (`*.d.ts`): Minimal rules for ambient types
- **JavaScript Files**: Basic linting without type checking
- **Library Exports** (`lib/**/*.ts`, `public-api.ts`): Stricter JSDoc requirements - all public classes, methods, and functions must be documented for better API documentation

## Additional Examples

### TypeScript Strictness
```typescript
// โŒ Unnecessary type operations
const value = data as unknown as string; // double assertion
type Same = T extends T ? T : never; // unnecessary constraint
if (typeof x === 'string') {
(x as string).length; // unnecessary assertion after guard
}

// โœ… Clean type handling
const value = data as string; // single assertion when needed
type Nullable = T | null; // simple and clear
if (typeof x === 'string') {
x.length; // TypeScript knows the type
}
```

### Template Expressions
```typescript
// โŒ Restricted template expressions
const msg = `Count: ${someObject}`; // Error: object in template
const id = `ID: ${null}`; // Error: null without handling

// โœ… Allowed template usage
const msg = `Count: ${count}`; // numbers allowed
const debug = `Data: ${JSON.stringify(obj)}`; // explicit conversion
const id = `ID: ${userId ?? 'unknown'}`; // null handled
```

### Function Return Types
```typescript
// โŒ Missing return types
function calculate(a: number, b: number) { // Error: needs return type
return a + b;
}

// โœ… Explicit return types (with smart exceptions)
function calculate(a: number, b: number): number {
return a + b;
}

// โœ… Exceptions that don't need explicit returns
const add = (a: number, b: number) => a + b; // arrow function expressions
const handler = () => console.log('done'); // void returns
```

## VSCode Integration

Add to `.vscode/settings.json`:

```json
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.experimental.useFlatConfig": true,
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
]
}
```

## Package.json Scripts

```json
{
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"lint:debug": "eslint . --debug",
"type-check": "tsc --noEmit"
}
}
```

## Migration from ESLint 8

1. Remove `.eslintrc.*` files
2. Create `eslint.config.js` with flat config
3. Update VSCode settings for flat config
4. Remove Prettier (this config handles formatting)

## Performance Tips

- Use `projectService: true` for better TypeScript performance
- Enable ESLint cache: `eslint . --cache`
- Exclude build directories in your tsconfig.json
- Consider using `--max-warnings 0` in CI/CD

## Philosophy

This configuration prioritizes:

1. **Type Safety** - Catch errors at build time, not runtime
2. **Consistency** - Unified formatting without Prettier
3. **Performance** - Optimized for large TypeScript projects
4. **Developer Experience** - Clear errors with practical rules

## License

MIT

## Contributing

Issues and PRs welcome at [GitHub](https://github.com/noneforge/eslint-config)