eslint-plugin-th-rules 2.2.0 β 2.5.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 +32 -0
- package/README.md +10 -9
- package/docs/rules/no-boolean-coercion.md +1 -1
- package/docs/rules/prefer-is-empty.md +5 -0
- package/package.json +1 -1
- package/src/rules/no-boolean-coercion.js +8 -3
- package/src/rules/prefer-is-empty.js +66 -0
- package/tests/no-boolean-coercion.test.ts +4 -8
- package/tests/prefer-is-empty.test.ts +68 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
|
+
# [2.5.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v2.4.0...v2.5.0) (2026-01-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add prefer-is-empty rule to enforce _.isEmpty over length comparisons and update documentation ([5bc671f](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/5bc671f35599d69a5a1432d173df408082da2db6))
|
|
7
|
+
|
|
8
|
+
# [2.4.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v2.3.0...v2.4.0) (2026-01-14)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* fixed git tags ([822f503](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/822f5033769f89fabbd6cf7177ccef74311ec2e5))
|
|
14
|
+
|
|
1
15
|
# [2.2.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v2.1.1...v2.2.0) (2026-01-14)
|
|
2
16
|
|
|
3
17
|
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* enhance no-boolean-coercion rule with detailed messages and update tests ([c79ad92](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/c79ad921e2a6c4dabe0f0e74b80393b01525c3d7))
|
|
21
|
+
* enhance no-boolean-coercion rule with detailed messages and update tests ([686d620](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/686d6204bd46f757a4490656521b1094f3e3237e))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Features
|
|
25
|
+
|
|
26
|
+
* created new rule no-boolean-coercion ([f9b0803](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/f9b08039f6275e363da10e8e3ca49fb75ad2e48a))
|
|
27
|
+
|
|
28
|
+
# [2.2.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v2.1.1...v2.2.0) (2026-01-14)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### Bug Fixes
|
|
32
|
+
|
|
33
|
+
* enhance no-boolean-coercion rule with detailed messages and update tests ([686d620](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/686d6204bd46f757a4490656521b1094f3e3237e))
|
|
34
|
+
|
|
35
|
+
|
|
4
36
|
### Features
|
|
5
37
|
|
|
6
38
|
* created new rule no-boolean-coercion ([f9b0803](https://github.com/tomerh2001/eslint-plugin-th-rules/commit/f9b08039f6275e363da10e8e3ca49fb75ad2e48a))
|
package/README.md
CHANGED
|
@@ -17,15 +17,16 @@ This repository contains custom ESLint rules to enhance code quality and consist
|
|
|
17
17
|
π§ Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
|
|
18
18
|
π‘ Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
|
|
19
19
|
|
|
20
|
-
| NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β | Description
|
|
21
|
-
| :--------------------------------------------------------------- |
|
|
22
|
-
| [no-boolean-coercion](docs/rules/no-boolean-coercion.md) | Disallow Boolean(
|
|
23
|
-
| [no-comments](docs/rules/no-comments.md) | Disallow comments except for specified allowed patterns.
|
|
24
|
-
| [no-default-export](docs/rules/no-default-export.md) | Convert unnamed default exports to named default exports based on the file name.
|
|
25
|
-
| [no-destructuring](docs/rules/no-destructuring.md) | Disallow destructuring that does not meet certain conditions
|
|
26
|
-
| [
|
|
27
|
-
| [
|
|
28
|
-
| [
|
|
20
|
+
| NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β | Description | πΌ | π§ | π‘ |
|
|
21
|
+
| :--------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- | :------ | :- | :- |
|
|
22
|
+
| [no-boolean-coercion](docs/rules/no-boolean-coercion.md) | Disallow Boolean(value) or !!value. Enforce _.isNil(value) for scalar values and _.isEmpty(value) for strings, arrays, and objects. | β
βοΈ π¦ | | π‘ |
|
|
23
|
+
| [no-comments](docs/rules/no-comments.md) | Disallow comments except for specified allowed patterns. | β
βοΈ π¦ | π§ | |
|
|
24
|
+
| [no-default-export](docs/rules/no-default-export.md) | Convert unnamed default exports to named default exports based on the file name. | β
βοΈ π¦ | π§ | |
|
|
25
|
+
| [no-destructuring](docs/rules/no-destructuring.md) | Disallow destructuring that does not meet certain conditions | β
βοΈ π¦ | | |
|
|
26
|
+
| [prefer-is-empty](docs/rules/prefer-is-empty.md) | Require _.isEmpty instead of length comparisons | | | |
|
|
27
|
+
| [schemas-in-schemas-file](docs/rules/schemas-in-schemas-file.md) | Require Zod schema declarations to be placed in a .schemas.ts file | β
βοΈ π¦ | | |
|
|
28
|
+
| [top-level-functions](docs/rules/top-level-functions.md) | Require all top-level functions to be named/regular functions. | β
βοΈ π¦ | π§ | |
|
|
29
|
+
| [types-in-dts](docs/rules/types-in-dts.md) | Require TypeScript type declarations (type/interface/enum) to be placed in .d.ts files | β
βοΈ π¦ | | |
|
|
29
30
|
|
|
30
31
|
<!-- end auto-generated rules list -->
|
|
31
32
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# th-rules/no-boolean-coercion
|
|
2
2
|
|
|
3
|
-
π Disallow Boolean(
|
|
3
|
+
π Disallow Boolean(value) or !!value. Enforce _.isNil(value) for scalar values and _.isEmpty(value) for strings, arrays, and objects.
|
|
4
4
|
|
|
5
5
|
πΌ This rule is enabled in the following configs: β
`recommended`, βοΈ `recommended-react`, π¦ `recommended-typescript`.
|
|
6
6
|
|
package/package.json
CHANGED
|
@@ -2,13 +2,19 @@ const meta = {
|
|
|
2
2
|
type: 'problem',
|
|
3
3
|
docs: {
|
|
4
4
|
description:
|
|
5
|
-
|
|
5
|
+
'Disallow Boolean(value) or !!value. Enforce _.isNil(value) for scalar values and _.isEmpty(value) for strings, arrays, and objects.',
|
|
6
6
|
category: 'Best Practices',
|
|
7
7
|
recommended: true,
|
|
8
8
|
url: 'https://github.com/tomerh2001/eslint-plugin-th-rules/blob/main/docs/rules/no-boolean-coercion.md',
|
|
9
9
|
},
|
|
10
10
|
hasSuggestions: true,
|
|
11
11
|
schema: [],
|
|
12
|
+
messages: {
|
|
13
|
+
useIsEmpty:
|
|
14
|
+
'Boolean coercion is not allowed. Use _.isEmpty(value) for strings, arrays, and objects.',
|
|
15
|
+
useIsNil:
|
|
16
|
+
'Boolean coercion is not allowed. Use _.isNil(value) for scalar values.',
|
|
17
|
+
},
|
|
12
18
|
};
|
|
13
19
|
|
|
14
20
|
function create(context) {
|
|
@@ -75,8 +81,7 @@ function create(context) {
|
|
|
75
81
|
|
|
76
82
|
context.report({
|
|
77
83
|
node,
|
|
78
|
-
|
|
79
|
-
'Boolean coercion is not allowed. Use an explicit null/empty check instead.',
|
|
84
|
+
messageId: isCollection ? 'useIsEmpty' : 'useIsNil',
|
|
80
85
|
suggest: [
|
|
81
86
|
{
|
|
82
87
|
desc: `Replace with ${replacement}`,
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const meta = {
|
|
2
|
+
type: 'problem',
|
|
3
|
+
docs: {
|
|
4
|
+
description: 'Require _.isEmpty instead of length comparisons',
|
|
5
|
+
category: 'Best Practices',
|
|
6
|
+
recommended: true,
|
|
7
|
+
url: 'https://github.com/tomerh2001/eslint-plugin-th-rules/blob/main/docs/rules/prefer-is-empty.md',
|
|
8
|
+
},
|
|
9
|
+
schema: [],
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
function create(context) {
|
|
13
|
+
function isLengthAccess(node) {
|
|
14
|
+
return (
|
|
15
|
+
node
|
|
16
|
+
&& node.type === 'MemberExpression'
|
|
17
|
+
&& !node.computed
|
|
18
|
+
&& node.property.type === 'Identifier'
|
|
19
|
+
&& node.property.name === 'length'
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isZeroOrOneLiteral(node) {
|
|
24
|
+
return (
|
|
25
|
+
node
|
|
26
|
+
&& node.type === 'Literal'
|
|
27
|
+
&& (node.value === 0 || node.value === 1)
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function report(node, collectionNode, operator, literalValue) {
|
|
32
|
+
const sourceCode = context.getSourceCode();
|
|
33
|
+
const collectionText = sourceCode.getText(collectionNode.object);
|
|
34
|
+
|
|
35
|
+
context.report({
|
|
36
|
+
node,
|
|
37
|
+
message: `Use _.isEmpty(${collectionText}) instead of checking ${collectionText}.length ${operator} ${literalValue}`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
BinaryExpression(node) {
|
|
43
|
+
const {left, right, operator} = node;
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
(operator === '>' || operator === '>=')
|
|
47
|
+
&& isLengthAccess(left)
|
|
48
|
+
&& isZeroOrOneLiteral(right)
|
|
49
|
+
) {
|
|
50
|
+
report(node, left, operator, right.value);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (
|
|
55
|
+
(operator === '!=' || operator === '!==')
|
|
56
|
+
&& isLengthAccess(left)
|
|
57
|
+
&& right?.type === 'Literal'
|
|
58
|
+
&& right.value === 0
|
|
59
|
+
) {
|
|
60
|
+
report(node, left, operator, 0);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {meta, create};
|
|
@@ -3,9 +3,6 @@ const rule = require('../src/rules/no-boolean-coercion');
|
|
|
3
3
|
|
|
4
4
|
const ruleTester = new RuleTester({});
|
|
5
5
|
|
|
6
|
-
const ERROR_MESSAGE
|
|
7
|
-
= 'Boolean coercion is not allowed. Use an explicit null/empty check instead.';
|
|
8
|
-
|
|
9
6
|
ruleTester.run('no-boolean-coercion', rule, {
|
|
10
7
|
valid: [
|
|
11
8
|
'_.isNil(value);',
|
|
@@ -22,7 +19,7 @@ ruleTester.run('no-boolean-coercion', rule, {
|
|
|
22
19
|
code: 'Boolean(foo);',
|
|
23
20
|
errors: [
|
|
24
21
|
{
|
|
25
|
-
|
|
22
|
+
messageId: 'useIsNil',
|
|
26
23
|
suggestions: [
|
|
27
24
|
{
|
|
28
25
|
desc: 'Replace with _.isNil(foo)',
|
|
@@ -37,7 +34,7 @@ ruleTester.run('no-boolean-coercion', rule, {
|
|
|
37
34
|
code: 'const x = Boolean(bar);',
|
|
38
35
|
errors: [
|
|
39
36
|
{
|
|
40
|
-
|
|
37
|
+
messageId: 'useIsNil',
|
|
41
38
|
suggestions: [
|
|
42
39
|
{
|
|
43
40
|
desc: 'Replace with _.isNil(bar)',
|
|
@@ -52,7 +49,7 @@ ruleTester.run('no-boolean-coercion', rule, {
|
|
|
52
49
|
code: '!!value;',
|
|
53
50
|
errors: [
|
|
54
51
|
{
|
|
55
|
-
|
|
52
|
+
messageId: 'useIsNil',
|
|
56
53
|
suggestions: [
|
|
57
54
|
{
|
|
58
55
|
desc: 'Replace with _.isNil(value)',
|
|
@@ -67,7 +64,7 @@ ruleTester.run('no-boolean-coercion', rule, {
|
|
|
67
64
|
code: 'Boolean([]);',
|
|
68
65
|
errors: [
|
|
69
66
|
{
|
|
70
|
-
|
|
67
|
+
messageId: 'useIsEmpty',
|
|
71
68
|
suggestions: [
|
|
72
69
|
{
|
|
73
70
|
desc: 'Replace with _.isEmpty([])',
|
|
@@ -77,6 +74,5 @@ ruleTester.run('no-boolean-coercion', rule, {
|
|
|
77
74
|
},
|
|
78
75
|
],
|
|
79
76
|
},
|
|
80
|
-
|
|
81
77
|
],
|
|
82
78
|
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const {RuleTester} = require('eslint');
|
|
2
|
+
const rule = require('../src/rules/prefer-is-empty');
|
|
3
|
+
|
|
4
|
+
const ruleTester = new RuleTester({});
|
|
5
|
+
|
|
6
|
+
ruleTester.run('prefer-is-empty', rule, {
|
|
7
|
+
valid: [
|
|
8
|
+
'_.isEmpty(values);',
|
|
9
|
+
'!_.isEmpty(values);',
|
|
10
|
+
'values.length === 0;',
|
|
11
|
+
'values.length <= 0;',
|
|
12
|
+
'values.length < 1;',
|
|
13
|
+
'Array.isArray(values);',
|
|
14
|
+
'values.size > 0;', // Non-length property
|
|
15
|
+
],
|
|
16
|
+
|
|
17
|
+
invalid: [
|
|
18
|
+
{
|
|
19
|
+
code: 'values.length > 0;',
|
|
20
|
+
errors: [
|
|
21
|
+
{
|
|
22
|
+
message:
|
|
23
|
+
'Use _.isEmpty(values) instead of checking values.length > 0',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
code: 'values.length >= 1;',
|
|
30
|
+
errors: [
|
|
31
|
+
{
|
|
32
|
+
message:
|
|
33
|
+
'Use _.isEmpty(values) instead of checking values.length >= 1',
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
{
|
|
39
|
+
code: 'values.length != 0;',
|
|
40
|
+
errors: [
|
|
41
|
+
{
|
|
42
|
+
message:
|
|
43
|
+
'Use _.isEmpty(values) instead of checking values.length != 0',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
{
|
|
49
|
+
code: 'values.length !== 0;',
|
|
50
|
+
errors: [
|
|
51
|
+
{
|
|
52
|
+
message:
|
|
53
|
+
'Use _.isEmpty(values) instead of checking values.length !== 0',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
{
|
|
59
|
+
code: 'if (items.length > 0) {}',
|
|
60
|
+
errors: [
|
|
61
|
+
{
|
|
62
|
+
message:
|
|
63
|
+
'Use _.isEmpty(items) instead of checking items.length > 0',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
});
|