eslint-plugin-remeda 1.5.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.
@@ -0,0 +1,89 @@
1
+ # remeda/prefer-has-atleast
2
+
3
+ 💼 This rule is enabled in the ✅ `recommended` config.
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ When checking if an array has at least a certain number of elements, it is more expressive to use `R.hasAtLeast` instead of comparing the array's length with a number.
8
+
9
+ Additionally, when checking if an array is not empty, it's better to use `R.hasAtLeast(data, 1)` instead of negated `R.isEmpty(data)` patterns (`!R.isEmpty(data)`) because the TypeScript type narrowing works better with `hasAtLeast`.
10
+
11
+ ## Rule Details
12
+
13
+ The following patterns are considered warnings:
14
+
15
+ ```js
16
+ // Array length comparisons
17
+ if (array.length >= 3) {
18
+ // ...
19
+ }
20
+
21
+ if (array.length > 2) {
22
+ // ...
23
+ }
24
+
25
+ if (3 <= array.length) {
26
+ // ...
27
+ }
28
+
29
+ if (2 < array.length) {
30
+ // ...
31
+ }
32
+
33
+ // Negated isEmpty patterns (problematic for TypeScript type narrowing)
34
+ if (!R.isEmpty(array)) {
35
+ // TypeScript won't narrow the array type here
36
+ }
37
+
38
+ if (R.isEmpty(array) === false) {
39
+ // Same issue with type narrowing
40
+ }
41
+
42
+ if (R.isEmpty(array) !== true) {
43
+ // Same issue with type narrowing
44
+ }
45
+ ```
46
+
47
+ The following patterns are not considered warnings:
48
+
49
+ ```js
50
+ // Using hasAtLeast
51
+ if (R.hasAtLeast(array, 3)) {
52
+ // ...
53
+ }
54
+
55
+ // For non-empty checks, use hasAtLeast with 1
56
+ if (R.hasAtLeast(array, 1)) {
57
+ // TypeScript correctly narrows the type here
58
+ }
59
+
60
+ // Other length comparisons
61
+ if (array.length === 3) {
62
+ // ...
63
+ }
64
+
65
+ if (array.length < 3) {
66
+ // ...
67
+ }
68
+
69
+ if (array.length <= 3) {
70
+ // ...
71
+ }
72
+
73
+ // Regular isEmpty checks are fine
74
+ if (R.isEmpty(array)) {
75
+ // ...
76
+ }
77
+ ```
78
+
79
+ ## Type Safety Improvement
80
+
81
+ From Remeda documentation:
82
+
83
+ > "This guard [isEmpty] doesn't work negated because of typescript limitations! If you need to check that an array is not empty, use R.hasAtLeast(data, 1) and not !R.isEmpty(data). For strings and objects there's no way in typescript to narrow the result to a non-empty type."
84
+
85
+ Using `R.hasAtLeast(array, 1)` instead of `!R.isEmpty(array)` improves type safety because TypeScript can properly narrow the array type to a non-empty array, which helps prevent "possibly undefined" errors when accessing array elements.
86
+
87
+ ## When Not To Use It
88
+
89
+ If you do not want to enforce using `R.hasAtLeast` or prefer the explicit array length comparison, you should not use this rule. However, consider enabling it at least for the negated `isEmpty` patterns to improve type safety.
package/package.json CHANGED
@@ -1,20 +1,19 @@
1
1
  {
2
2
  "name": "eslint-plugin-remeda",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "author": "Andrea Pontrandolfo <andrea.pontra@gmail.com>",
5
5
  "description": "ESLint plugin for Remeda library.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "scripts": {
9
- "build": "tsup",
9
+ "build": "tsdown",
10
10
  "typecheck": "tsc",
11
11
  "lint": "eslint",
12
12
  "knip": "knip",
13
- "publint": "publint",
14
13
  "test:watch": "vitest --ui",
15
14
  "test": "vitest run",
16
15
  "attw": "attw --pack .",
17
- "qa": "pnpm typecheck && pnpm test && pnpm knip && pnpm publint && attw",
16
+ "qa": "pnpm typecheck && pnpm test && pnpm knip && attw",
18
17
  "nuke": "rm -rf node_modules pnpm-lock.yaml",
19
18
  "update:eslint-docs": "eslint-doc-generator",
20
19
  "lint:eslint-docs": "pnpm update:eslint-docs -- --check",
@@ -22,14 +21,21 @@
22
21
  },
23
22
  "files": [
24
23
  "README.md",
24
+ "LICENSE",
25
25
  "dist",
26
26
  "docs"
27
27
  ],
28
28
  "exports": {
29
29
  "./package.json": "./package.json",
30
30
  ".": {
31
- "import": "./dist/index.js",
32
- "default": "./dist/index.cjs"
31
+ "import": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/index.d.cts",
37
+ "require": "./dist/index.cjs"
38
+ }
33
39
  }
34
40
  },
35
41
  "repository": {
@@ -42,24 +48,26 @@
42
48
  "eslint": ">=9.0.0"
43
49
  },
44
50
  "devDependencies": {
45
- "@arethetypeswrong/cli": "^0.15.4",
51
+ "@arethetypeswrong/cli": "^0.17.4",
52
+ "@sherifforg/cli": "^8.2.0",
46
53
  "@types/lodash-es": "^4.17.12",
47
- "@types/node": "^20.14.9",
48
- "@vitest/coverage-v8": "^2.0.3",
49
- "@vitest/ui": "^2.0.3",
50
- "eslint": "9.10.0",
51
- "eslint-config-sheriff": "^21.2.0",
52
- "eslint-define-config": "^2.1.0",
54
+ "@types/node": "^22.14.0",
55
+ "@typescript-eslint/utils": "^8.29.0",
56
+ "@vitest/coverage-v8": "^3.1.1",
57
+ "@vitest/ui": "^3.1.1",
58
+ "eslint": "9.24.0",
59
+ "eslint-config-sheriff": "^27.0.0",
53
60
  "eslint-doc-generator": "^2.1.2",
54
61
  "eslint-plugin-eslint-plugin": "^6.4.0",
55
- "eslint-vitest-rule-tester": "^0.3.3",
56
- "knip": "^5.29.1",
62
+ "eslint-vitest-rule-tester": "^2.2.0",
63
+ "knip": "^5.49.0",
64
+ "lodash-es": "^4.17.21",
57
65
  "prettier": "^3.3.2",
58
- "publint": "^0.2.10",
66
+ "publint": "^0.3.10",
59
67
  "semantic-release": "^24.0.0",
60
- "tsup": "^8.2.4",
68
+ "tsdown": "^0.9.1",
61
69
  "typescript": "^5.5.2",
62
- "vitest": "^2.0.3"
70
+ "vitest": "^3.1.1"
63
71
  },
64
72
  "engines": {
65
73
  "node": ">=20"
@@ -78,7 +86,5 @@
78
86
  "fp"
79
87
  ],
80
88
  "license": "MIT",
81
- "dependencies": {
82
- "lodash-es": "^4.17.21"
83
- }
89
+ "sideEffects": false
84
90
  }