eslint-plugin-nextfriday 1.5.3 → 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.
@@ -0,0 +1,144 @@
1
+ # jsx-no-variable-in-callback
2
+
3
+ Disallow variable declarations inside callback functions within JSX.
4
+
5
+ ## Rule Details
6
+
7
+ This rule prevents variable declarations inside callback functions that are directly used within JSX expressions. This enforces cleaner, more maintainable code by extracting complex logic to separate functions.
8
+
9
+ ### Why?
10
+
11
+ 1. **Readability**: Keeps JSX clean and focused on rendering, not logic
12
+ 2. **Maintainability**: Extracted functions are easier to test and modify
13
+ 3. **Separation of Concerns**: Logic belongs in functions, not inline in JSX
14
+ 4. **Consistency**: Enforces a uniform pattern across the codebase
15
+
16
+ ## Examples
17
+
18
+ ### ❌ Incorrect
19
+
20
+ ```tsx
21
+ // Bad: Variable declared inside map callback in JSX
22
+ const UserList = ({ users }) => {
23
+ return (
24
+ <div>
25
+ {users.map((user) => {
26
+ const displayName = user.firstName + " " + user.lastName;
27
+ return <div key={user.id}>{displayName}</div>;
28
+ })}
29
+ </div>
30
+ );
31
+ };
32
+ ```
33
+
34
+ ```tsx
35
+ // Bad: Variable in filter callback
36
+ const ProductList = ({ products }) => {
37
+ return (
38
+ <ul>
39
+ {products.filter((product) => {
40
+ const isAvailable = product.stock > 0 && product.active;
41
+ return isAvailable;
42
+ })}
43
+ </ul>
44
+ );
45
+ };
46
+ ```
47
+
48
+ ```tsx
49
+ // Bad: Multiple variables in callback
50
+ const OrderSummary = ({ orders }) => {
51
+ return (
52
+ <div>
53
+ {orders.map((order) => {
54
+ const total = order.price * order.quantity;
55
+ const discount = total * 0.1;
56
+ const final = total - discount;
57
+ return <div key={order.id}>{final}</div>;
58
+ })}
59
+ </div>
60
+ );
61
+ };
62
+ ```
63
+
64
+ ### ✅ Correct
65
+
66
+ ```tsx
67
+ // Good: Extract logic to a separate function
68
+ const UserList = ({ users }) => {
69
+ const renderUsers = () =>
70
+ users.map((user) => {
71
+ const displayName = user.firstName + " " + user.lastName;
72
+ return <div key={user.id}>{displayName}</div>;
73
+ });
74
+
75
+ return <div>{renderUsers()}</div>;
76
+ };
77
+ ```
78
+
79
+ ```tsx
80
+ // Good: Use helper function outside JSX
81
+ const ProductList = ({ products }) => {
82
+ const isProductAvailable = (product) => {
83
+ const isAvailable = product.stock > 0 && product.active;
84
+ return isAvailable;
85
+ };
86
+
87
+ return <ul>{products.filter(isProductAvailable)}</ul>;
88
+ };
89
+ ```
90
+
91
+ ```tsx
92
+ // Good: No variable declaration in callback
93
+ const UserList = ({ users }) => {
94
+ return (
95
+ <div>
96
+ {users.map((user) => (
97
+ <div key={user.id}>
98
+ {user.firstName} {user.lastName}
99
+ </div>
100
+ ))}
101
+ </div>
102
+ );
103
+ };
104
+ ```
105
+
106
+ ```tsx
107
+ // Good: Variable declared outside JSX
108
+ const OrderSummary = ({ orders }) => {
109
+ const discount = 0.1;
110
+
111
+ return (
112
+ <div>
113
+ {orders.map((order) => {
114
+ const total = order.price * order.quantity;
115
+ return <div key={order.id}>{total - total * discount}</div>;
116
+ })}
117
+ </div>
118
+ );
119
+ };
120
+ ```
121
+
122
+ ```tsx
123
+ // Good: Extract rendering to a function
124
+ const OrderSummary = ({ orders }) => {
125
+ const calculateFinalPrice = (order) => {
126
+ const total = order.price * order.quantity;
127
+ const discount = total * 0.1;
128
+ return total - discount;
129
+ };
130
+
131
+ const renderOrders = () => orders.map((order) => <div key={order.id}>{calculateFinalPrice(order)}</div>);
132
+
133
+ return <div>{renderOrders()}</div>;
134
+ };
135
+ ```
136
+
137
+ ## When Not To Use It
138
+
139
+ If you prefer keeping all logic inline within JSX callbacks and don't mind the reduced readability, you can disable this rule. However, this is generally not recommended as it leads to harder-to-maintain code.
140
+
141
+ ## Further Reading
142
+
143
+ - [React Component Best Practices](https://react.dev/learn/keeping-components-pure)
144
+ - [Clean Code Principles](https://clean-code-developer.com/)
@@ -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
@@ -0,0 +1,78 @@
1
+ # prefer-jsx-template-literals
2
+
3
+ Enforce using template literals instead of mixing text and JSX expressions.
4
+
5
+ ## Rule Details
6
+
7
+ This rule prevents mixing plain text with JSX expressions in JSX elements, which can lead to incorrect spacing and readability issues. Instead, it enforces using template literals to combine text and expressions.
8
+
9
+ ### Why?
10
+
11
+ Mixing text and JSX expressions without proper spacing can cause:
12
+
13
+ 1. **Spacing issues**: `<div>+ {value}</div>` renders as "+ value" with unexpected spacing
14
+ 2. **Inconsistent formatting**: Hard to maintain consistent spacing across the codebase
15
+ 3. **Readability problems**: Mixed syntax makes code harder to read and understand
16
+
17
+ Using template literals ensures:
18
+
19
+ - Explicit control over spacing
20
+ - Consistent formatting
21
+ - Better readability
22
+ - Easier to maintain
23
+
24
+ ## Examples
25
+
26
+ ### ❌ Incorrect
27
+
28
+ ```tsx
29
+ // Bad: Text followed by expression
30
+ <div>+ {fooVariable}</div>
31
+ <div>+{fooVariable}</div>
32
+ <div>Price: {price}</div>
33
+ <div>$ {amount}</div>
34
+ <span>Total: {total}</span>
35
+ <p>Hello {name}</p>
36
+
37
+ // Bad: Expression followed by text
38
+ <div>{count} items</div>
39
+ <div>{price}$</div>
40
+ ```
41
+
42
+ ### ✅ Correct
43
+
44
+ ```tsx
45
+ // Good: Using template literals
46
+ <div>{`+${fooVariable}`}</div>
47
+ <div>{`+ ${fooVariable}`}</div>
48
+ <div>{`Price: ${price}`}</div>
49
+ <div>{`$ ${amount}`}</div>
50
+ <span>{`Total: ${total}`}</span>
51
+ <p>{`Hello ${name}`}</p>
52
+
53
+ // Good: Using template literals for expression + text
54
+ <div>{`${count}items`}</div>
55
+ <div>{`${price}$`}</div>
56
+
57
+ // Good: Expression only
58
+ <div>{fooVariable}</div>
59
+ <div>{price}</div>
60
+
61
+ // Good: Text only
62
+ <div>Some static text</div>
63
+
64
+ // Good: Expression with whitespace only around it
65
+ <div> {fooVariable} </div>
66
+ <div>
67
+ {fooVariable}
68
+ </div>
69
+ ```
70
+
71
+ ## When Not To Use It
72
+
73
+ If you prefer mixing text and JSX expressions, you can disable this rule. However, this may lead to inconsistent spacing and formatting issues.
74
+
75
+ ## Further Reading
76
+
77
+ - [Template Literals (MDN)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)
78
+ - [JSX in React](https://react.dev/learn/writing-markup-with-jsx)
@@ -0,0 +1,130 @@
1
+ # require-explicit-return-type
2
+
3
+ Require explicit return types on functions for better code documentation and type safety.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces that all functions have explicit return type annotations. Explicit return types serve as documentation, help catch bugs early, and make the codebase more maintainable.
8
+
9
+ **Incorrect** code for this rule:
10
+
11
+ ```typescript
12
+ function getName() {
13
+ return "John Doe";
14
+ }
15
+
16
+ const getAge = () => {
17
+ return 25;
18
+ };
19
+
20
+ function processUser() {
21
+ console.log("Processing user");
22
+ }
23
+
24
+ const calculateTotal = (items: Item[]) => {
25
+ return items.reduce((sum, item) => sum + item.price, 0);
26
+ };
27
+
28
+ async function fetchData() {
29
+ return await api.get("/data");
30
+ }
31
+
32
+ export function validateEmail(email: string) {
33
+ return email.includes("@");
34
+ }
35
+ ```
36
+
37
+ **Correct** code for this rule:
38
+
39
+ ```typescript
40
+ function getName(): string {
41
+ return "John Doe";
42
+ }
43
+
44
+ const getAge = (): number => {
45
+ return 25;
46
+ };
47
+
48
+ function processUser(): void {
49
+ console.log("Processing user");
50
+ }
51
+
52
+ const calculateTotal = (items: Item[]): number => {
53
+ return items.reduce((sum, item) => sum + item.price, 0);
54
+ };
55
+
56
+ async function fetchData(): Promise<Data> {
57
+ return await api.get("/data");
58
+ }
59
+
60
+ export function validateEmail(email: string): boolean {
61
+ return email.includes("@");
62
+ }
63
+ ```
64
+
65
+ ## Exceptions
66
+
67
+ This rule does NOT require return types for:
68
+
69
+ ### Callback Functions
70
+
71
+ ```typescript
72
+ // All of these are allowed without return types
73
+ items.map((item) => item.name);
74
+ items.filter((item) => item.active);
75
+ items.forEach((item) => console.log(item));
76
+ setTimeout(() => console.log("done"), 1000);
77
+ promise.then((result) => result.data);
78
+ ```
79
+
80
+ ### Object Properties
81
+
82
+ ```typescript
83
+ const handler = {
84
+ onClick: () => console.log("clicked"),
85
+ };
86
+ ```
87
+
88
+ ### Array Elements
89
+
90
+ ```typescript
91
+ const callbacks = [() => 1, () => 2];
92
+ ```
93
+
94
+ ### React Components (PascalCase)
95
+
96
+ ```typescript
97
+ // React components don't need explicit return types
98
+ const MyComponent = () => <div>Hello</div>;
99
+
100
+ function UserProfile() {
101
+ return <div>User</div>;
102
+ }
103
+
104
+ const Button = () => {
105
+ return <button>Click</button>;
106
+ };
107
+ ```
108
+
109
+ ## Benefits
110
+
111
+ - **Self-documenting code**: Return types serve as documentation for function contracts
112
+ - **Early error detection**: Type mismatches are caught at compile time
113
+ - **Better IDE support**: Explicit types improve autocomplete and refactoring
114
+ - **API clarity**: Public functions have clear type signatures
115
+ - **Maintainability**: Easier to understand function behavior at a glance
116
+
117
+ ## When Not To Use
118
+
119
+ - When you prefer TypeScript's type inference for all functions
120
+ - In rapid prototyping where explicit types slow down development
121
+ - When the inferred type is exactly what you want
122
+
123
+ ## Configuration
124
+
125
+ This rule has no configuration options.
126
+
127
+ ## Related Rules
128
+
129
+ - [@typescript-eslint/explicit-function-return-type](https://typescript-eslint.io/rules/explicit-function-return-type/) - Similar rule from typescript-eslint
130
+ - [@typescript-eslint/explicit-module-boundary-types](https://typescript-eslint.io/rules/explicit-module-boundary-types/) - Requires explicit types on exported functions