eslint-plugin-nextfriday 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +120 -74
- package/docs/rules/BOOLEAN_NAMING_PREFIX.md +102 -0
- package/docs/rules/NO_DIRECT_DATE.md +36 -0
- package/docs/rules/NO_SINGLE_CHAR_VARIABLES.md +108 -0
- package/docs/rules/PREFER_FUNCTION_DECLARATION.md +139 -0
- package/docs/rules/REQUIRE_EXPLICIT_RETURN_TYPE.md +130 -0
- package/lib/index.cjs +673 -217
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +70 -14
- package/lib/index.d.ts +70 -14
- package/lib/index.js +674 -218
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/docs/rules/NO_EXPLICIT_RETURN_TYPE.md +0 -71
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# eslint-plugin-nextfriday
|
|
2
2
|
|
|
3
|
+
## 1.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#41](https://github.com/next-friday/eslint-plugin-nextfriday/pull/41) [`10b67d9`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/10b67d941c47fef5b72408bfff2b56e98a46c26c) Thanks [@nextfridaydeveloper](https://github.com/nextfridaydeveloper)! - Add no-direct-date rule to disallow direct usage of Date constructor and methods (new Date(), Date.now(), Date.parse()) to enforce centralized date utilities like dayjs
|
|
8
|
+
|
|
3
9
|
## 1.6.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ pnpm add -D eslint-plugin-nextfriday
|
|
|
22
22
|
import nextfriday from "eslint-plugin-nextfriday";
|
|
23
23
|
|
|
24
24
|
export default [nextfriday.configs.base];
|
|
25
|
-
// or use the recommended preset
|
|
25
|
+
// or use the recommended preset (stricter)
|
|
26
26
|
export default [nextfriday.configs["base/recommended"]];
|
|
27
27
|
```
|
|
28
28
|
|
|
@@ -59,19 +59,37 @@ export default [
|
|
|
59
59
|
nextfriday,
|
|
60
60
|
},
|
|
61
61
|
rules: {
|
|
62
|
-
|
|
62
|
+
// Variable Naming
|
|
63
|
+
"nextfriday/no-single-char-variables": "error",
|
|
64
|
+
"nextfriday/boolean-naming-prefix": "error",
|
|
65
|
+
|
|
66
|
+
// File Naming
|
|
63
67
|
"nextfriday/file-kebab-case": "error",
|
|
68
|
+
"nextfriday/jsx-pascal-case": "error",
|
|
64
69
|
"nextfriday/md-filename-case-restriction": "error",
|
|
70
|
+
|
|
71
|
+
// Code Style
|
|
72
|
+
"nextfriday/no-emoji": "error",
|
|
65
73
|
"nextfriday/prefer-destructuring-params": "error",
|
|
66
|
-
"nextfriday/
|
|
67
|
-
"nextfriday/
|
|
68
|
-
"nextfriday/prefer-named-param-types": "error",
|
|
69
|
-
"nextfriday/prefer-react-import-types": "error",
|
|
74
|
+
"nextfriday/prefer-function-declaration": "error",
|
|
75
|
+
"nextfriday/require-explicit-return-type": "error",
|
|
70
76
|
"nextfriday/no-complex-inline-return": "error",
|
|
71
77
|
"nextfriday/no-logic-in-params": "error",
|
|
78
|
+
"nextfriday/enforce-sorted-destructuring": "error",
|
|
72
79
|
"nextfriday/no-env-fallback": "error",
|
|
73
|
-
|
|
80
|
+
|
|
81
|
+
// Import Optimization
|
|
82
|
+
"nextfriday/prefer-import-type": "error",
|
|
83
|
+
"nextfriday/prefer-react-import-types": "error",
|
|
84
|
+
|
|
85
|
+
// Type Patterns
|
|
86
|
+
"nextfriday/prefer-named-param-types": "error",
|
|
74
87
|
"nextfriday/prefer-interface-over-inline-types": "error",
|
|
88
|
+
|
|
89
|
+
// React/JSX
|
|
90
|
+
"nextfriday/jsx-no-non-component-function": "error",
|
|
91
|
+
"nextfriday/jsx-no-variable-in-callback": "error",
|
|
92
|
+
"nextfriday/prefer-jsx-template-literals": "error",
|
|
75
93
|
"nextfriday/react-props-destructure": "error",
|
|
76
94
|
"nextfriday/enforce-readonly-component-props": "error",
|
|
77
95
|
},
|
|
@@ -110,91 +128,119 @@ module.exports = {
|
|
|
110
128
|
|
|
111
129
|
## Rules
|
|
112
130
|
|
|
113
|
-
|
|
114
|
-
| -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------- |
|
|
115
|
-
| [no-emoji](docs/rules/NO_EMOJI.md) | Disallow emojis in code | ❌ |
|
|
116
|
-
| [file-kebab-case](docs/rules/FILE_KEBAB_CASE.md) | Enforce kebab-case filenames for .ts and .js files | ❌ |
|
|
117
|
-
| [jsx-pascal-case](docs/rules/JSX_PASCAL_CASE.md) | Enforce PascalCase filenames for .jsx and .tsx files | ❌ |
|
|
118
|
-
| [md-filename-case-restriction](docs/rules/MD_FILENAME_CASE_RESTRICTION.md) | Enforce SNAKE_CASE filenames for .md files | ❌ |
|
|
119
|
-
| [prefer-destructuring-params](docs/rules/PREFER_DESTRUCTURING_PARAMS.md) | Enforce destructuring for functions with multiple parameters | ❌ |
|
|
120
|
-
| [no-explicit-return-type](docs/rules/NO_EXPLICIT_RETURN_TYPE.md) | Disallow explicit return types on functions | ✅ |
|
|
121
|
-
| [jsx-no-non-component-function](docs/rules/JSX_NO_NON_COMPONENT_FUNCTION.md) | Disallow non-component functions at top level in .tsx and .jsx files | ❌ |
|
|
122
|
-
| [jsx-no-variable-in-callback](docs/rules/JSX_NO_VARIABLE_IN_CALLBACK.md) | Disallow variable declarations inside callback functions within JSX | ❌ |
|
|
123
|
-
| [prefer-import-type](docs/rules/PREFER_IMPORT_TYPE.md) | Enforce using 'import type' for type-only imports | ✅ |
|
|
124
|
-
| [prefer-named-param-types](docs/rules/PREFER_NAMED_PARAM_TYPES.md) | Enforce named types for function parameters with object types | ❌ |
|
|
125
|
-
| [prefer-interface-over-inline-types](docs/rules/PREFER_INTERFACE_OVER_INLINE_TYPES.md) | Enforce interface declarations over inline types for React props | ❌ |
|
|
126
|
-
| [prefer-jsx-template-literals](docs/rules/PREFER_JSX_TEMPLATE_LITERALS.md) | Enforce using template literals instead of mixing text and JSX expressions | ✅ |
|
|
127
|
-
| [prefer-react-import-types](docs/rules/PREFER_REACT_IMPORT_TYPES.md) | Enforce direct imports from 'react' instead of React.X | ✅ |
|
|
128
|
-
| [react-props-destructure](docs/rules/REACT_PROPS_DESTRUCTURE.md) | Enforce destructuring props inside React component body | ❌ |
|
|
129
|
-
| [enforce-readonly-component-props](docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md) | Enforce Readonly wrapper for React component props | ✅ |
|
|
130
|
-
| [enforce-sorted-destructuring](docs/rules/ENFORCE_SORTED_DESTRUCTURING.md) | Enforce alphabetical sorting of destructured properties with defaults first | ❌ |
|
|
131
|
-
| [no-complex-inline-return](docs/rules/NO_COMPLEX_INLINE_RETURN.md) | Disallow complex inline expressions in return statements - prefer const first | ❌ |
|
|
132
|
-
| [no-logic-in-params](docs/rules/NO_LOGIC_IN_PARAMS.md) | Disallow logic or conditions in function parameters - extract to const first | ❌ |
|
|
133
|
-
| [no-env-fallback](docs/rules/NO_ENV_FALLBACK.md) | Disallow fallback values for environment variables as they can be dangerous | ❌ |
|
|
134
|
-
|
|
135
|
-
## Configurations
|
|
136
|
-
|
|
137
|
-
### Base Configurations (for pure JS/TS projects)
|
|
138
|
-
|
|
139
|
-
#### `base`
|
|
140
|
-
|
|
141
|
-
Basic configuration without JSX-specific rules:
|
|
131
|
+
### Variable Naming Rules
|
|
142
132
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
- `nextfriday/no-explicit-return-type`: `"error"`
|
|
148
|
-
- `nextfriday/prefer-import-type`: `"error"`
|
|
149
|
-
- `nextfriday/prefer-named-param-types`: `"error"`
|
|
150
|
-
- `nextfriday/prefer-react-import-types`: `"error"`
|
|
151
|
-
- `nextfriday/no-complex-inline-return`: `"error"`
|
|
152
|
-
- `nextfriday/no-logic-in-params`: `"error"`
|
|
153
|
-
- `nextfriday/no-env-fallback`: `"error"`
|
|
133
|
+
| Rule | Description | Fixable |
|
|
134
|
+
| ------------------------------------------------------------------ | --------------------------------------------------------------------- | ------- |
|
|
135
|
+
| [no-single-char-variables](docs/rules/NO_SINGLE_CHAR_VARIABLES.md) | Disallow single character variable names (e.g., `d`, `u`, `l`) | ❌ |
|
|
136
|
+
| [boolean-naming-prefix](docs/rules/BOOLEAN_NAMING_PREFIX.md) | Enforce boolean variables to have prefix (is, has, should, can, etc.) | ❌ |
|
|
154
137
|
|
|
155
|
-
|
|
138
|
+
### File Naming Rules
|
|
156
139
|
|
|
157
|
-
|
|
140
|
+
| Rule | Description | Fixable |
|
|
141
|
+
| -------------------------------------------------------------------------- | ---------------------------------------------------- | ------- |
|
|
142
|
+
| [file-kebab-case](docs/rules/FILE_KEBAB_CASE.md) | Enforce kebab-case filenames for .ts and .js files | ❌ |
|
|
143
|
+
| [jsx-pascal-case](docs/rules/JSX_PASCAL_CASE.md) | Enforce PascalCase filenames for .jsx and .tsx files | ❌ |
|
|
144
|
+
| [md-filename-case-restriction](docs/rules/MD_FILENAME_CASE_RESTRICTION.md) | Enforce SNAKE_CASE filenames for .md files | ❌ |
|
|
158
145
|
|
|
159
|
-
###
|
|
146
|
+
### Code Style Rules
|
|
160
147
|
|
|
161
|
-
|
|
148
|
+
| Rule | Description | Fixable |
|
|
149
|
+
| -------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------- |
|
|
150
|
+
| [no-emoji](docs/rules/NO_EMOJI.md) | Disallow emoji characters in source code | ❌ |
|
|
151
|
+
| [prefer-destructuring-params](docs/rules/PREFER_DESTRUCTURING_PARAMS.md) | Enforce destructuring for functions with multiple parameters | ❌ |
|
|
152
|
+
| [prefer-function-declaration](docs/rules/PREFER_FUNCTION_DECLARATION.md) | Enforce function declarations over arrow functions in .ts files | ❌ |
|
|
153
|
+
| [require-explicit-return-type](docs/rules/REQUIRE_EXPLICIT_RETURN_TYPE.md) | Require explicit return types on functions for better documentation | ❌ |
|
|
154
|
+
| [no-complex-inline-return](docs/rules/NO_COMPLEX_INLINE_RETURN.md) | Disallow complex inline expressions in return - extract to const first | ❌ |
|
|
155
|
+
| [no-logic-in-params](docs/rules/NO_LOGIC_IN_PARAMS.md) | Disallow logic/conditions in function parameters - extract to const | ❌ |
|
|
156
|
+
| [enforce-sorted-destructuring](docs/rules/ENFORCE_SORTED_DESTRUCTURING.md) | Enforce alphabetical sorting of destructured properties | ❌ |
|
|
157
|
+
| [no-env-fallback](docs/rules/NO_ENV_FALLBACK.md) | Disallow fallback values for environment variables | ❌ |
|
|
158
|
+
| [no-direct-date](docs/rules/NO_DIRECT_DATE.md) | Disallow direct usage of Date constructor and methods | ❌ |
|
|
162
159
|
|
|
163
|
-
|
|
160
|
+
### Import Optimization Rules
|
|
164
161
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
-
|
|
169
|
-
- `nextfriday/enforce-readonly-component-props`: `"error"`
|
|
162
|
+
| Rule | Description | Fixable |
|
|
163
|
+
| -------------------------------------------------------------------- | ------------------------------------------------------ | ------- |
|
|
164
|
+
| [prefer-import-type](docs/rules/PREFER_IMPORT_TYPE.md) | Enforce using 'import type' for type-only imports | ✅ |
|
|
165
|
+
| [prefer-react-import-types](docs/rules/PREFER_REACT_IMPORT_TYPES.md) | Enforce direct imports from 'react' instead of React.X | ✅ |
|
|
170
166
|
|
|
171
|
-
|
|
167
|
+
### Type Pattern Rules
|
|
172
168
|
|
|
173
|
-
|
|
169
|
+
| Rule | Description | Fixable |
|
|
170
|
+
| -------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------- |
|
|
171
|
+
| [prefer-named-param-types](docs/rules/PREFER_NAMED_PARAM_TYPES.md) | Enforce named types for function parameters with object types | ❌ |
|
|
172
|
+
| [prefer-interface-over-inline-types](docs/rules/PREFER_INTERFACE_OVER_INLINE_TYPES.md) | Enforce interface declarations over inline types for React props | ❌ |
|
|
174
173
|
|
|
175
|
-
###
|
|
174
|
+
### React/JSX Rules
|
|
176
175
|
|
|
177
|
-
|
|
176
|
+
| Rule | Description | Fixable |
|
|
177
|
+
| ---------------------------------------------------------------------------------- | -------------------------------------------------------------------- | ------- |
|
|
178
|
+
| [jsx-no-non-component-function](docs/rules/JSX_NO_NON_COMPONENT_FUNCTION.md) | Disallow non-component functions at top level in .tsx/.jsx files | ❌ |
|
|
179
|
+
| [jsx-no-variable-in-callback](docs/rules/JSX_NO_VARIABLE_IN_CALLBACK.md) | Disallow variable declarations inside callback functions in JSX | ❌ |
|
|
180
|
+
| [prefer-jsx-template-literals](docs/rules/PREFER_JSX_TEMPLATE_LITERALS.md) | Enforce template literals instead of mixing text and JSX expressions | ✅ |
|
|
181
|
+
| [react-props-destructure](docs/rules/REACT_PROPS_DESTRUCTURE.md) | Enforce destructuring props inside React component body | ❌ |
|
|
182
|
+
| [enforce-readonly-component-props](docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md) | Enforce Readonly wrapper for React component props | ✅ |
|
|
178
183
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
- All base rules
|
|
182
|
-
- `nextfriday/jsx-pascal-case`: `"error"`
|
|
183
|
-
- `nextfriday/prefer-interface-over-inline-types`: `"error"`
|
|
184
|
-
- `nextfriday/react-props-destructure`: `"error"`
|
|
185
|
-
- `nextfriday/enforce-readonly-component-props`: `"error"`
|
|
186
|
-
|
|
187
|
-
#### `nextjs/recommended`
|
|
184
|
+
## Configurations
|
|
188
185
|
|
|
189
|
-
|
|
186
|
+
### Configuration Presets Overview
|
|
187
|
+
|
|
188
|
+
| Preset | Severity | Base Rules | JSX Rules | Total Rules |
|
|
189
|
+
| -------------------- | -------- | ---------- | --------- | ----------- |
|
|
190
|
+
| `base` | warn | 16 | 0 | 16 |
|
|
191
|
+
| `base/recommended` | error | 16 | 0 | 16 |
|
|
192
|
+
| `react` | warn | 16 | 7 | 23 |
|
|
193
|
+
| `react/recommended` | error | 16 | 7 | 23 |
|
|
194
|
+
| `nextjs` | warn | 16 | 7 | 23 |
|
|
195
|
+
| `nextjs/recommended` | error | 16 | 7 | 23 |
|
|
196
|
+
|
|
197
|
+
### Base Configuration Rules (16 rules)
|
|
198
|
+
|
|
199
|
+
Included in `base`, `base/recommended`, and all other presets:
|
|
200
|
+
|
|
201
|
+
- `nextfriday/boolean-naming-prefix`
|
|
202
|
+
- `nextfriday/enforce-sorted-destructuring`
|
|
203
|
+
- `nextfriday/file-kebab-case`
|
|
204
|
+
- `nextfriday/md-filename-case-restriction`
|
|
205
|
+
- `nextfriday/no-complex-inline-return`
|
|
206
|
+
- `nextfriday/no-direct-date`
|
|
207
|
+
- `nextfriday/no-emoji`
|
|
208
|
+
- `nextfriday/no-env-fallback`
|
|
209
|
+
- `nextfriday/require-explicit-return-type`
|
|
210
|
+
- `nextfriday/no-logic-in-params`
|
|
211
|
+
- `nextfriday/no-single-char-variables`
|
|
212
|
+
- `nextfriday/prefer-destructuring-params`
|
|
213
|
+
- `nextfriday/prefer-function-declaration`
|
|
214
|
+
- `nextfriday/prefer-import-type`
|
|
215
|
+
- `nextfriday/prefer-named-param-types`
|
|
216
|
+
- `nextfriday/prefer-react-import-types`
|
|
217
|
+
|
|
218
|
+
### JSX Rules (7 rules)
|
|
219
|
+
|
|
220
|
+
Additionally included in `react`, `react/recommended`, `nextjs`, `nextjs/recommended`:
|
|
221
|
+
|
|
222
|
+
- `nextfriday/enforce-readonly-component-props`
|
|
223
|
+
- `nextfriday/jsx-no-non-component-function`
|
|
224
|
+
- `nextfriday/jsx-no-variable-in-callback`
|
|
225
|
+
- `nextfriday/jsx-pascal-case`
|
|
226
|
+
- `nextfriday/prefer-interface-over-inline-types`
|
|
227
|
+
- `nextfriday/prefer-jsx-template-literals`
|
|
228
|
+
- `nextfriday/react-props-destructure`
|
|
229
|
+
|
|
230
|
+
### Severity Levels
|
|
231
|
+
|
|
232
|
+
- **`base` / `react` / `nextjs`**: All rules set to `"warn"`
|
|
233
|
+
- **`base/recommended` / `react/recommended` / `nextjs/recommended`**: All rules set to `"error"`
|
|
190
234
|
|
|
191
235
|
## Features
|
|
192
236
|
|
|
193
|
-
- **
|
|
237
|
+
- **Variable naming enforcement**: Prevent cryptic single-character names and enforce boolean prefixes
|
|
238
|
+
- **File naming enforcement**: Ensure consistent file naming conventions (kebab-case, PascalCase, SNAKE_CASE)
|
|
239
|
+
- **Function style**: Enforce function declarations over arrow functions in utility files
|
|
194
240
|
- **Import optimization**: Automatically suggests better import patterns for TypeScript
|
|
195
241
|
- **Code cleanup**: Helps remove unnecessary explicit type annotations
|
|
196
|
-
- **React component conventions**: Enforces naming standards for JSX/TSX files
|
|
197
|
-
- **Clean code practices**: Prevents emoji usage
|
|
242
|
+
- **React component conventions**: Enforces naming standards and patterns for JSX/TSX files
|
|
243
|
+
- **Clean code practices**: Prevents emoji usage, enforces parameter destructuring, and more
|
|
198
244
|
|
|
199
245
|
## Need Help?
|
|
200
246
|
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# boolean-naming-prefix
|
|
2
|
+
|
|
3
|
+
Enforce boolean variables and parameters to have a prefix like is, has, should, can, did, will for better readability.
|
|
4
|
+
|
|
5
|
+
## Rule Details
|
|
6
|
+
|
|
7
|
+
This rule enforces that boolean variables and parameters use a descriptive prefix that makes them read like English sentences. Variables like `open`, `valid`, `user` are ambiguous - it's unclear whether they represent a value or a state. Boolean prefixes make the intent clear.
|
|
8
|
+
|
|
9
|
+
**Recommended prefixes:** `is`, `has`, `should`, `can`, `did`, `will`, `was`, `are`, `does`, `had`
|
|
10
|
+
|
|
11
|
+
**Incorrect** code for this rule:
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
const valid = true;
|
|
15
|
+
const user = false;
|
|
16
|
+
const open = true;
|
|
17
|
+
const closed = false;
|
|
18
|
+
const active: boolean = true;
|
|
19
|
+
const enabled: boolean = checkEnabled();
|
|
20
|
+
|
|
21
|
+
const equal = a === b;
|
|
22
|
+
const different = a !== b;
|
|
23
|
+
const bigger = a > b;
|
|
24
|
+
const negated = !value;
|
|
25
|
+
const combined = a && b;
|
|
26
|
+
const either = a || b;
|
|
27
|
+
|
|
28
|
+
function process(active: boolean) {}
|
|
29
|
+
const fn = (enabled: boolean) => {};
|
|
30
|
+
function toggle(active = true) {}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Correct** code for this rule:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
const isValid = true;
|
|
37
|
+
const hasUser = false;
|
|
38
|
+
const isOpen = true;
|
|
39
|
+
const isClosed = false;
|
|
40
|
+
const isActive: boolean = true;
|
|
41
|
+
const isEnabled: boolean = checkEnabled();
|
|
42
|
+
|
|
43
|
+
const isEqual = a === b;
|
|
44
|
+
const isDifferent = a !== b;
|
|
45
|
+
const isBigger = a > b;
|
|
46
|
+
const isNegated = !value;
|
|
47
|
+
const areCombined = a && b;
|
|
48
|
+
const hasEither = a || b;
|
|
49
|
+
|
|
50
|
+
function process(isActive: boolean) {}
|
|
51
|
+
const fn = (hasAccess: boolean) => {};
|
|
52
|
+
function toggle(isActive = true) {}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## What This Rule Detects
|
|
56
|
+
|
|
57
|
+
The rule identifies boolean variables and parameters by:
|
|
58
|
+
|
|
59
|
+
1. **Boolean type annotations**: Variables explicitly typed as `boolean`
|
|
60
|
+
2. **Boolean literals**: Variables initialized with `true` or `false`
|
|
61
|
+
3. **Comparison expressions**: `===`, `!==`, `==`, `!=`, `<`, `>`, `<=`, `>=`, `in`, `instanceof`
|
|
62
|
+
4. **Logical expressions**: `&&`, `||`
|
|
63
|
+
5. **Negation**: `!value`
|
|
64
|
+
6. **Function parameters**: With boolean type annotation or default boolean value
|
|
65
|
+
|
|
66
|
+
## Allowed Prefixes
|
|
67
|
+
|
|
68
|
+
| Prefix | Usage | Example |
|
|
69
|
+
| -------- | ----------------------------- | --------------------------------------------- |
|
|
70
|
+
| `is` | State or condition | `isActive`, `isValid`, `isLoading` |
|
|
71
|
+
| `has` | Possession or existence | `hasUser`, `hasPermission`, `hasError` |
|
|
72
|
+
| `can` | Ability or permission | `canSubmit`, `canEdit`, `canDelete` |
|
|
73
|
+
| `should` | Recommendation or expectation | `shouldRender`, `shouldUpdate`, `shouldFetch` |
|
|
74
|
+
| `will` | Future action | `willUpdate`, `willRedirect`, `willExpire` |
|
|
75
|
+
| `did` | Past action | `didLoad`, `didSubmit`, `didFail` |
|
|
76
|
+
| `was` | Past state | `wasActive`, `wasVisible`, `wasProcessed` |
|
|
77
|
+
| `are` | Plural state | `areEqual`, `areValid`, `areLoaded` |
|
|
78
|
+
| `does` | Action capability | `doesExist`, `doesMatch`, `doesContain` |
|
|
79
|
+
| `had` | Past possession | `hadError`, `hadAccess`, `hadPrevious` |
|
|
80
|
+
|
|
81
|
+
## Benefits
|
|
82
|
+
|
|
83
|
+
- **Self-documenting code**: Boolean intent is immediately clear
|
|
84
|
+
- **Reads like English**: `if (isActive)` reads as "if is active"
|
|
85
|
+
- **Reduced ambiguity**: `user = false` vs `hasUser = false` - the latter is clear
|
|
86
|
+
- **Consistent codebase**: Enforces uniform boolean naming across the project
|
|
87
|
+
- **Better code review**: Reviewers can quickly understand boolean logic
|
|
88
|
+
|
|
89
|
+
## When Not To Use
|
|
90
|
+
|
|
91
|
+
- When working with external APIs that return boolean fields with different naming conventions
|
|
92
|
+
- In mathematical or scientific code where single-letter variables are conventional
|
|
93
|
+
- When interfacing with legacy code that would require extensive refactoring
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
This rule has no configuration options.
|
|
98
|
+
|
|
99
|
+
## Related Rules
|
|
100
|
+
|
|
101
|
+
- [no-single-char-variables](./NO_SINGLE_CHAR_VARIABLES.md) - Disallows single character variable names
|
|
102
|
+
- [@typescript-eslint/naming-convention](https://typescript-eslint.io/rules/naming-convention/) - More comprehensive naming convention rule
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# no-direct-date
|
|
2
|
+
|
|
3
|
+
Disallow direct usage of Date constructor and methods to enforce centralized date utilities.
|
|
4
|
+
|
|
5
|
+
## Rule Details
|
|
6
|
+
|
|
7
|
+
This rule prevents the use of the native JavaScript `Date` constructor and its static methods (`Date.now()`, `Date.parse()`). Using a centralized date utility library like dayjs, date-fns, or Luxon provides better consistency, easier testing, and more predictable date handling across your application.
|
|
8
|
+
|
|
9
|
+
## Examples
|
|
10
|
+
|
|
11
|
+
**Incorrect** code for this rule:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
const now = new Date();
|
|
15
|
+
const timestamp = Date.now();
|
|
16
|
+
const parsed = Date.parse("2024-01-01");
|
|
17
|
+
const specificDate = new Date("2024-01-01");
|
|
18
|
+
const dateFromTimestamp = new Date(1704067200000);
|
|
19
|
+
const dateFromParts = new Date(2024, 0, 1);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Correct** code for this rule:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
import dayjs from "dayjs";
|
|
26
|
+
|
|
27
|
+
const now = dayjs();
|
|
28
|
+
const timestamp = dayjs().valueOf();
|
|
29
|
+
const parsed = dayjs("2024-01-01");
|
|
30
|
+
const specificDate = dayjs("2024-01-01");
|
|
31
|
+
const dateFromTimestamp = dayjs(1704067200000);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## When Not To Use It
|
|
35
|
+
|
|
36
|
+
If your project does not use a centralized date utility library and you prefer to work directly with the native JavaScript Date API, you can disable this rule.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# no-single-char-variables
|
|
2
|
+
|
|
3
|
+
Disallow single character variable and parameter names for better code readability.
|
|
4
|
+
|
|
5
|
+
## Rule Details
|
|
6
|
+
|
|
7
|
+
This rule enforces descriptive variable and parameter names by disallowing single character identifiers. Single character names like `d`, `u`, `l`, `r` are cryptic and make code harder to understand. They require readers to guess or track what each variable represents.
|
|
8
|
+
|
|
9
|
+
**Incorrect** code for this rule:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
const d = new Date();
|
|
13
|
+
const u = await getUser();
|
|
14
|
+
const l = list.length;
|
|
15
|
+
const r = await fetch(url);
|
|
16
|
+
|
|
17
|
+
users.map((u) => u.id);
|
|
18
|
+
onClick((e) => e.preventDefault());
|
|
19
|
+
|
|
20
|
+
const add = (a, b) => a + b;
|
|
21
|
+
const e = (x) => x * 2;
|
|
22
|
+
|
|
23
|
+
function f() {
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const { a } = obj;
|
|
28
|
+
const [x] = array;
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
} catch (e) {}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Correct** code for this rule:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
const currentDate = new Date();
|
|
38
|
+
const currentUser = await getUser();
|
|
39
|
+
const itemCount = list.length;
|
|
40
|
+
const response = await fetch(url);
|
|
41
|
+
|
|
42
|
+
users.map((user) => user.id);
|
|
43
|
+
onClick((event) => event.preventDefault());
|
|
44
|
+
|
|
45
|
+
const add = (val1, val2) => val1 + val2;
|
|
46
|
+
const add = (width, height) => width * height;
|
|
47
|
+
const calculateDouble = (value) => value * 2;
|
|
48
|
+
|
|
49
|
+
function getName() {
|
|
50
|
+
return "test";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const { alpha } = obj;
|
|
54
|
+
const { a: alpha } = obj;
|
|
55
|
+
const [first] = array;
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
} catch (error) {}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Exceptions
|
|
62
|
+
|
|
63
|
+
The rule allows the following exceptions:
|
|
64
|
+
|
|
65
|
+
### Loop Counters
|
|
66
|
+
|
|
67
|
+
Single character loop counters `i`, `j`, `k`, `n` are allowed in traditional for loops:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
for (let i = 0; i < 10; i++) {}
|
|
71
|
+
for (let j = 0; j < items.length; j++) {}
|
|
72
|
+
for (let i = 0, j = 10; i < j; i++, j--) {}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Note: These are only allowed in traditional `for` loops, not in `for...of` or `for...in` loops.
|
|
76
|
+
|
|
77
|
+
### Underscore for Unused Variables
|
|
78
|
+
|
|
79
|
+
A single underscore `_` is allowed to indicate intentionally unused variables:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const _ = unusedValue;
|
|
83
|
+
const [_, second] = array;
|
|
84
|
+
array.map((_, index) => index);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Benefits
|
|
88
|
+
|
|
89
|
+
- **Self-documenting code**: Descriptive names make code readable without additional comments
|
|
90
|
+
- **Reduced cognitive load**: No need to track or guess what single letters represent
|
|
91
|
+
- **Better IDE support**: Meaningful names provide better autocomplete and search results
|
|
92
|
+
- **Easier debugging**: Clear variable names make debugging and code review faster
|
|
93
|
+
- **Improved collaboration**: Team members can understand code without additional context
|
|
94
|
+
|
|
95
|
+
## When Not To Use
|
|
96
|
+
|
|
97
|
+
- For very short scripts or throwaway code
|
|
98
|
+
- When working with mathematical formulas where single letters are conventional (e.g., `x`, `y` for coordinates)
|
|
99
|
+
- In legacy codebases where this pattern is established and changing would be disruptive
|
|
100
|
+
|
|
101
|
+
## Configuration
|
|
102
|
+
|
|
103
|
+
This rule has no configuration options.
|
|
104
|
+
|
|
105
|
+
## Related Rules
|
|
106
|
+
|
|
107
|
+
- [prefer-destructuring-params](./PREFER_DESTRUCTURING_PARAMS.md) - Encourages destructuring for function parameters
|
|
108
|
+
- [prefer-named-param-types](./PREFER_NAMED_PARAM_TYPES.md) - Encourages named parameters for better readability
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# prefer-function-declaration
|
|
2
|
+
|
|
3
|
+
Enforce function declarations over arrow functions assigned to variables in `.ts` files for better readability and hoisting.
|
|
4
|
+
|
|
5
|
+
## Rule Details
|
|
6
|
+
|
|
7
|
+
This rule requires using function declarations instead of arrow functions or function expressions when defining named functions in TypeScript utility files. Arrow functions used as callbacks (in `.map()`, `.filter()`, etc.) are still allowed.
|
|
8
|
+
|
|
9
|
+
**Target:** `.ts` files only (not `.tsx`, `.js`, or `.d.ts`)
|
|
10
|
+
|
|
11
|
+
**Incorrect** code for this rule:
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// utils/date.ts
|
|
15
|
+
const formatThaiDate = (date: Date) => {
|
|
16
|
+
return date.toLocaleDateString("th-TH");
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const formatDate = (date: Date) => date.toISOString();
|
|
20
|
+
|
|
21
|
+
export const add = (a: number, b: number) => a + b;
|
|
22
|
+
|
|
23
|
+
const greet = function (name: string) {
|
|
24
|
+
return `Hello ${name}`;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const fetchUser = async (id: string) => {
|
|
28
|
+
return await api.get(`/users/${id}`);
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Correct** code for this rule:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// utils/date.ts
|
|
36
|
+
function formatThaiDate(date: Date) {
|
|
37
|
+
return date.toLocaleDateString("th-TH");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function formatDate(date: Date) {
|
|
41
|
+
return date.toISOString();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function add(a: number, b: number) {
|
|
45
|
+
return a + b;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function greet(name: string) {
|
|
49
|
+
return `Hello ${name}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function fetchUser(id: string) {
|
|
53
|
+
return await api.get(`/users/${id}`);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## What This Rule Allows
|
|
58
|
+
|
|
59
|
+
Arrow functions are still allowed in the following contexts:
|
|
60
|
+
|
|
61
|
+
### Callbacks
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// All of these are allowed
|
|
65
|
+
const years = dates.map((date) => date.getFullYear());
|
|
66
|
+
const active = items.filter((item) => item.active);
|
|
67
|
+
const sorted = items.sort((a, b) => a.name.localeCompare(b.name));
|
|
68
|
+
items.forEach((item) => console.log(item));
|
|
69
|
+
const total = items.reduce((sum, item) => sum + item.price, 0);
|
|
70
|
+
setTimeout(() => console.log("done"), 1000);
|
|
71
|
+
promise.then((result) => result.data);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Object Properties
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
const handler = {
|
|
78
|
+
onClick: () => console.log("clicked"),
|
|
79
|
+
onHover: () => setHovered(true),
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Array Elements
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
const callbacks = [() => 1, () => 2, () => 3];
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Return Values
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
function createHandler() {
|
|
93
|
+
return () => console.log("handled");
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Conditional/Logical Expressions
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const fn = condition ? () => valueA : () => valueB;
|
|
101
|
+
const handler = defaultFn || (() => fallback);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### TSX Files
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// components/Button.tsx - Arrow functions allowed
|
|
108
|
+
const Button = () => <button>Click me</button>;
|
|
109
|
+
const handleClick = () => console.log("clicked");
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Benefits
|
|
113
|
+
|
|
114
|
+
- **Hoisting**: Function declarations are hoisted, allowing you to call functions before they're defined
|
|
115
|
+
- **Better readability**: Function declarations are more explicit about intent
|
|
116
|
+
- **Clearer stack traces**: Named function declarations provide better debugging information
|
|
117
|
+
- **Consistent style**: Enforces uniform function definition patterns in utility files
|
|
118
|
+
- **Self-documenting**: `function formatDate()` is clearer than `const formatDate = () =>`
|
|
119
|
+
|
|
120
|
+
## Why Only `.ts` Files?
|
|
121
|
+
|
|
122
|
+
- **`.tsx` files**: Arrow functions are commonly used for React components and event handlers
|
|
123
|
+
- **`.js` files**: JavaScript projects may have different conventions
|
|
124
|
+
- **`.d.ts` files**: Declaration files don't contain implementations
|
|
125
|
+
|
|
126
|
+
## When Not To Use
|
|
127
|
+
|
|
128
|
+
- When you prefer arrow functions for all function definitions
|
|
129
|
+
- In projects where arrow function style is established
|
|
130
|
+
- When you need lexical `this` binding (arrow functions don't have their own `this`)
|
|
131
|
+
|
|
132
|
+
## Configuration
|
|
133
|
+
|
|
134
|
+
This rule has no configuration options.
|
|
135
|
+
|
|
136
|
+
## Related Rules
|
|
137
|
+
|
|
138
|
+
- [func-style](https://eslint.org/docs/rules/func-style) - Built-in ESLint rule for function style
|
|
139
|
+
- [arrow-body-style](https://eslint.org/docs/rules/arrow-body-style) - Enforce arrow function body style
|