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.
- package/CHANGELOG.md +15 -0
- package/README.md +120 -70
- package/docs/rules/BOOLEAN_NAMING_PREFIX.md +102 -0
- package/docs/rules/ENFORCE_SORTED_DESTRUCTURING.md +122 -0
- package/docs/rules/JSX_NO_NON_COMPONENT_FUNCTION.md +114 -0
- package/docs/rules/JSX_NO_VARIABLE_IN_CALLBACK.md +144 -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/PREFER_JSX_TEMPLATE_LITERALS.md +78 -0
- package/docs/rules/REQUIRE_EXPLICIT_RETURN_TYPE.md +130 -0
- package/lib/index.cjs +1078 -172
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +126 -14
- package/lib/index.d.ts +126 -14
- package/lib/index.js +1079 -173
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/docs/rules/NO_EXPLICIT_RETURN_TYPE.md +0 -71
|
@@ -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
|