eslint-plugin-th-rules 2.4.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 CHANGED
@@ -1,3 +1,10 @@
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
+
1
8
  # [2.4.0](https://github.com/tomerh2001/eslint-plugin-th-rules/compare/v2.3.0...v2.4.0) (2026-01-14)
2
9
 
3
10
 
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(variable) or !!variable and enforce explicit _.isNil / _.isEmpty checks | βœ… βš›οΈ 🟦 | | πŸ’‘ |
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
- | [schemas-in-schemas-file](docs/rules/schemas-in-schemas-file.md) | Require Zod schema declarations to be placed in a .schemas.ts file | βœ… βš›οΈ 🟦 | | |
27
- | [top-level-functions](docs/rules/top-level-functions.md) | Require all top-level functions to be named/regular functions. | βœ… βš›οΈ 🟦 | πŸ”§ | |
28
- | [types-in-dts](docs/rules/types-in-dts.md) | Require TypeScript type declarations (type/interface/enum) to be placed in .d.ts files | βœ… βš›οΈ 🟦 | | |
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(variable) or !!variable and enforce explicit _.isNil / _.isEmpty checks.
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
 
@@ -0,0 +1,5 @@
1
+ # th-rules/prefer-is-empty
2
+
3
+ πŸ“ Require _.isEmpty instead of length comparisons.
4
+
5
+ <!-- end auto-generated rule header -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-th-rules",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "A List of custom ESLint rules created by Tomer Horowitz",
5
5
  "keywords": [
6
6
  "eslint",
@@ -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};
@@ -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
+ });