eslint-plugin-ts-data-forge 0.8.0 → 0.8.2

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.
Files changed (95) hide show
  1. package/dist/rules/ast-utils.d.mts.map +1 -1
  2. package/dist/rules/ast-utils.mjs +24 -24
  3. package/dist/rules/ast-utils.mjs.map +1 -1
  4. package/dist/rules/branded-number-types.mjs.map +1 -1
  5. package/dist/rules/import-utils.d.mts.map +1 -1
  6. package/dist/rules/import-utils.mjs +4 -2
  7. package/dist/rules/import-utils.mjs.map +1 -1
  8. package/dist/rules/no-unnecessary-type-guard.d.mts.map +1 -1
  9. package/dist/rules/no-unnecessary-type-guard.mjs +37 -23
  10. package/dist/rules/no-unnecessary-type-guard.mjs.map +1 -1
  11. package/dist/rules/prefer-arr-is-array.d.mts.map +1 -1
  12. package/dist/rules/prefer-arr-is-array.mjs +14 -7
  13. package/dist/rules/prefer-arr-is-array.mjs.map +1 -1
  14. package/dist/rules/prefer-arr-is-bounded-length-array.d.mts.map +1 -1
  15. package/dist/rules/prefer-arr-is-bounded-length-array.mjs +8 -4
  16. package/dist/rules/prefer-arr-is-bounded-length-array.mjs.map +1 -1
  17. package/dist/rules/prefer-arr-is-fixed-length-array.d.mts.map +1 -1
  18. package/dist/rules/prefer-arr-is-fixed-length-array.mjs +8 -4
  19. package/dist/rules/prefer-arr-is-fixed-length-array.mjs.map +1 -1
  20. package/dist/rules/prefer-arr-is-max-length-array.d.mts.map +1 -1
  21. package/dist/rules/prefer-arr-is-max-length-array.mjs +10 -5
  22. package/dist/rules/prefer-arr-is-max-length-array.mjs.map +1 -1
  23. package/dist/rules/prefer-arr-is-min-length-array.d.mts.map +1 -1
  24. package/dist/rules/prefer-arr-is-min-length-array.mjs +10 -5
  25. package/dist/rules/prefer-arr-is-min-length-array.mjs.map +1 -1
  26. package/dist/rules/prefer-arr-is-non-empty.d.mts.map +1 -1
  27. package/dist/rules/prefer-arr-is-non-empty.mjs +4 -2
  28. package/dist/rules/prefer-arr-is-non-empty.mjs.map +1 -1
  29. package/dist/rules/prefer-arr-scan.d.mts.map +1 -1
  30. package/dist/rules/prefer-arr-scan.mjs +35 -18
  31. package/dist/rules/prefer-arr-scan.mjs.map +1 -1
  32. package/dist/rules/prefer-arr-sum.d.mts.map +1 -1
  33. package/dist/rules/prefer-arr-sum.mjs +6 -3
  34. package/dist/rules/prefer-arr-sum.mjs.map +1 -1
  35. package/dist/rules/prefer-arr-uniq.d.mts.map +1 -1
  36. package/dist/rules/prefer-arr-uniq.mjs +30 -24
  37. package/dist/rules/prefer-arr-uniq.mjs.map +1 -1
  38. package/dist/rules/prefer-as-int.d.mts.map +1 -1
  39. package/dist/rules/prefer-as-int.mjs +11 -14
  40. package/dist/rules/prefer-as-int.mjs.map +1 -1
  41. package/dist/rules/prefer-canonical-array-slicing.d.mts.map +1 -1
  42. package/dist/rules/prefer-canonical-array-slicing.mjs +32 -16
  43. package/dist/rules/prefer-canonical-array-slicing.mjs.map +1 -1
  44. package/dist/rules/prefer-canonical-length-cast.d.mts.map +1 -1
  45. package/dist/rules/prefer-canonical-length-cast.mjs +11 -7
  46. package/dist/rules/prefer-canonical-length-cast.mjs.map +1 -1
  47. package/dist/rules/prefer-canonical-length-guard.d.mts.map +1 -1
  48. package/dist/rules/prefer-canonical-length-guard.mjs +8 -4
  49. package/dist/rules/prefer-canonical-length-guard.mjs.map +1 -1
  50. package/dist/rules/prefer-comparison-over-nullish-guard.d.mts.map +1 -1
  51. package/dist/rules/prefer-comparison-over-nullish-guard.mjs +6 -3
  52. package/dist/rules/prefer-comparison-over-nullish-guard.mjs.map +1 -1
  53. package/dist/rules/prefer-is-non-null-object.d.mts.map +1 -1
  54. package/dist/rules/prefer-is-non-null-object.mjs +29 -31
  55. package/dist/rules/prefer-is-non-null-object.mjs.map +1 -1
  56. package/dist/rules/prefer-is-record-and-has-key.d.mts.map +1 -1
  57. package/dist/rules/prefer-is-record-and-has-key.mjs +10 -5
  58. package/dist/rules/prefer-is-record-and-has-key.mjs.map +1 -1
  59. package/dist/rules/prefer-num-safe-parse-float.d.mts.map +1 -1
  60. package/dist/rules/prefer-num-safe-parse-float.mjs +12 -6
  61. package/dist/rules/prefer-num-safe-parse-float.mjs.map +1 -1
  62. package/dist/rules/prefer-num-safe-parse-int.d.mts.map +1 -1
  63. package/dist/rules/prefer-num-safe-parse-int.mjs +12 -6
  64. package/dist/rules/prefer-num-safe-parse-int.mjs.map +1 -1
  65. package/dist/rules/prefer-obj-over-entries-round-trip.d.mts.map +1 -1
  66. package/dist/rules/prefer-obj-over-entries-round-trip.mjs +22 -11
  67. package/dist/rules/prefer-obj-over-entries-round-trip.mjs.map +1 -1
  68. package/dist/rules/prefer-range-for-loop.d.mts.map +1 -1
  69. package/dist/rules/prefer-range-for-loop.mjs +2 -1
  70. package/dist/rules/prefer-range-for-loop.mjs.map +1 -1
  71. package/package.json +25 -24
  72. package/src/rules/ast-utils.mts +38 -26
  73. package/src/rules/branded-number-types.mts +1 -1
  74. package/src/rules/import-utils.mts +6 -2
  75. package/src/rules/no-unnecessary-type-guard.mts +56 -23
  76. package/src/rules/prefer-arr-is-array.mts +21 -7
  77. package/src/rules/prefer-arr-is-bounded-length-array.mts +12 -4
  78. package/src/rules/prefer-arr-is-fixed-length-array.mts +12 -4
  79. package/src/rules/prefer-arr-is-max-length-array.mts +15 -5
  80. package/src/rules/prefer-arr-is-min-length-array.mts +15 -5
  81. package/src/rules/prefer-arr-is-non-empty.mts +6 -2
  82. package/src/rules/prefer-arr-scan.mts +52 -18
  83. package/src/rules/prefer-arr-sum.mts +9 -3
  84. package/src/rules/prefer-arr-uniq.mts +42 -26
  85. package/src/rules/prefer-as-int.mts +17 -25
  86. package/src/rules/prefer-canonical-array-slicing.mts +48 -16
  87. package/src/rules/prefer-canonical-length-cast.mts +15 -7
  88. package/src/rules/prefer-canonical-length-guard.mts +12 -4
  89. package/src/rules/prefer-comparison-over-nullish-guard.mts +9 -3
  90. package/src/rules/prefer-is-non-null-object.mts +35 -31
  91. package/src/rules/prefer-is-record-and-has-key.mts +15 -5
  92. package/src/rules/prefer-num-safe-parse-float.mts +17 -6
  93. package/src/rules/prefer-num-safe-parse-int.mts +18 -6
  94. package/src/rules/prefer-obj-over-entries-round-trip.mts +33 -11
  95. package/src/rules/prefer-range-for-loop.mts +3 -1
@@ -79,18 +79,25 @@ export const preferArrUniq: TSESLint.RuleModule<MessageIds, Options> = {
79
79
  ): void => {
80
80
  const arrayExpression = getSetSourceArray(setNode);
81
81
 
82
- if (arrayExpression === undefined) return;
82
+ if (arrayExpression === undefined) {
83
+ return;
84
+ }
83
85
 
84
- if (!isGlobal(sourceCode, node, 'Set')) return;
86
+ if (!isGlobal(sourceCode, node, 'Set')) {
87
+ return;
88
+ }
85
89
 
86
90
  const arrayTsNode = getTsNode(arrayExpression);
87
91
 
88
- if (arrayTsNode === undefined) return;
92
+ if (arrayTsNode === undefined) {
93
+ return;
94
+ }
89
95
 
90
96
  if (
91
97
  !isPrimitiveArrayType(checker, checker.getTypeAtLocation(arrayTsNode))
92
- )
98
+ ) {
93
99
  return;
100
+ }
94
101
 
95
102
  mut_matches.push({
96
103
  node,
@@ -117,17 +124,23 @@ export const preferArrUniq: TSESLint.RuleModule<MessageIds, Options> = {
117
124
  return;
118
125
  }
119
126
 
120
- if (!isGlobal(sourceCode, node, 'Array')) return;
127
+ if (!isGlobal(sourceCode, node, 'Array')) {
128
+ return;
129
+ }
121
130
 
122
131
  check(node, node.arguments[0]);
123
132
  },
124
133
  ArrayExpression: (node) => {
125
134
  // [...new Set(xs)]
126
- if (!Arr.isFixedLengthTuple(1, node.elements)) return;
135
+ if (!Arr.isFixedLengthTuple(1, node.elements)) {
136
+ return;
137
+ }
127
138
 
128
139
  const element = node.elements[0];
129
140
 
130
- if (element?.type !== AST_NODE_TYPES.SpreadElement) return;
141
+ if (element?.type !== AST_NODE_TYPES.SpreadElement) {
142
+ return;
143
+ }
131
144
 
132
145
  check(node, element.argument);
133
146
  },
@@ -246,11 +259,10 @@ const findVariable = (
246
259
  ): TSESLint.Scope.Variable | undefined => {
247
260
  const variable = scope.set.get(name);
248
261
 
249
- if (variable !== undefined) return variable;
250
-
251
- if (scope.upper === null) return undefined;
252
-
253
- return findVariable(scope.upper, name);
262
+ return (
263
+ variable ??
264
+ (scope.upper === null ? undefined : findVariable(scope.upper, name))
265
+ );
254
266
  };
255
267
 
256
268
  /**
@@ -296,11 +308,9 @@ const isPrimitiveType = (
296
308
  ): boolean => {
297
309
  const resolved = resolveConstraint(checker, type);
298
310
 
299
- if (resolved.isUnion()) {
300
- return resolved.types.every((t) => isPrimitiveType(checker, t));
301
- }
302
-
303
- return (resolved.flags & primitiveTypeFlags) !== 0;
311
+ return resolved.isUnion()
312
+ ? resolved.types.every((t) => isPrimitiveType(checker, t))
313
+ : (resolved.flags & primitiveTypeFlags) !== 0;
304
314
  };
305
315
 
306
316
  const primitiveTypeFlags =
@@ -338,7 +348,9 @@ const needsMutableResult = (
338
348
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
339
349
  node: TSESTree.Node,
340
350
  ): boolean => {
341
- if (isUsedAsMutable(checker, getTsNode, node)) return true;
351
+ if (isUsedAsMutable(checker, getTsNode, node)) {
352
+ return true;
353
+ }
342
354
 
343
355
  const parent = node.parent;
344
356
 
@@ -401,9 +413,13 @@ const isUsedAsMutable = (
401
413
  // whose declared type is a mutable array.
402
414
  const tsNode = getTsNode(node);
403
415
 
404
- if (tsNode === undefined) return false;
416
+ if (tsNode === undefined) {
417
+ return false;
418
+ }
405
419
 
406
- if (!ts.isExpression(tsNode)) return false;
420
+ if (!ts.isExpression(tsNode)) {
421
+ return false;
422
+ }
407
423
 
408
424
  const expectedType =
409
425
  getDeclaredParameterType(checker, tsNode) ??
@@ -436,7 +452,9 @@ const getDeclaredParameterType = (
436
452
 
437
453
  const index = call.arguments?.indexOf(argument) ?? -1;
438
454
 
439
- if (index === -1) return undefined;
455
+ if (index === -1) {
456
+ return undefined;
457
+ }
440
458
 
441
459
  const declaration = checker.getResolvedSignature(call)?.getDeclaration();
442
460
 
@@ -444,11 +462,9 @@ const getDeclaredParameterType = (
444
462
 
445
463
  // A rest parameter's declared type is the array of arguments, not the type of
446
464
  // one; the contextual type is the better answer there.
447
- if (parameter === undefined || parameter.dotDotDotToken !== undefined) {
448
- return undefined;
449
- }
450
-
451
- return checker.getTypeAtLocation(parameter);
465
+ return parameter === undefined || parameter.dotDotDotToken !== undefined
466
+ ? undefined
467
+ : checker.getTypeAtLocation(parameter);
452
468
  };
453
469
 
454
470
  /**
@@ -47,7 +47,9 @@ export const preferAsInt: TSESLint.RuleModule<MessageIds, Options> = {
47
47
  TSAsExpression: (node) => {
48
48
  const typeInfo = getBrandedNumberTypeInfo(node.typeAnnotation);
49
49
 
50
- if (typeInfo === undefined) return;
50
+ if (typeInfo === undefined) {
51
+ return;
52
+ }
51
53
 
52
54
  mut_nodesToFix.push({
53
55
  node,
@@ -59,26 +61,13 @@ export const preferAsInt: TSESLint.RuleModule<MessageIds, Options> = {
59
61
  const namedImports = getNamedImports(tsDataForgeImport);
60
62
 
61
63
  // Group nodes by function name to handle imports efficiently
62
- const mut_functionNameToNodes = new Map<
63
- string,
64
- Readonly<{
65
- node: TSESTree.TSAsExpression;
66
- typeName: string;
67
- functionName: string;
68
- }>[]
69
- >();
70
-
71
- for (const nodeInfo of mut_nodesToFix) {
72
- const mut_nodes =
73
- mut_functionNameToNodes.get(nodeInfo.functionName) ?? [];
74
-
75
- mut_nodes.push(nodeInfo);
76
-
77
- mut_functionNameToNodes.set(nodeInfo.functionName, mut_nodes);
78
- }
64
+ const functionNameToNodes = Map.groupBy(
65
+ mut_nodesToFix,
66
+ (nodeInfo) => nodeInfo.functionName,
67
+ );
79
68
 
80
69
  // Process each group
81
- for (const [functionName, nodes] of mut_functionNameToNodes) {
70
+ for (const [functionName, nodes] of functionNameToNodes) {
82
71
  const hasImport = namedImports.includes(functionName);
83
72
 
84
73
  for (const [index, { node, typeName }] of nodes.entries()) {
@@ -114,18 +103,21 @@ export const preferAsInt: TSESLint.RuleModule<MessageIds, Options> = {
114
103
  const getBrandedNumberTypeInfo = (
115
104
  typeAnnotation: DeepReadonly<TSESTree.TypeNode>,
116
105
  ): Readonly<{ typeName: string; functionName: string }> | undefined => {
117
- if (typeAnnotation.type !== AST_NODE_TYPES.TSTypeReference) return undefined;
106
+ if (typeAnnotation.type !== AST_NODE_TYPES.TSTypeReference) {
107
+ return undefined;
108
+ }
118
109
 
119
- if (typeAnnotation.typeName.type !== AST_NODE_TYPES.Identifier)
110
+ if (typeAnnotation.typeName.type !== AST_NODE_TYPES.Identifier) {
120
111
  return undefined;
112
+ }
121
113
 
122
114
  const typeName = typeAnnotation.typeName.name;
123
115
 
124
- if (!brandedNumberTypeNameToFunctionName.has(typeName)) return undefined;
116
+ if (!brandedNumberTypeNameToFunctionName.has(typeName)) {
117
+ return undefined;
118
+ }
125
119
 
126
120
  const functionName = brandedNumberTypeNameToFunctionName.get(typeName);
127
121
 
128
- if (functionName === undefined) return undefined;
129
-
130
- return { typeName, functionName };
122
+ return functionName === undefined ? undefined : { typeName, functionName };
131
123
  };
@@ -421,7 +421,9 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
421
421
  return classifyLiteralComparison(op, n);
422
422
  }
423
423
 
424
- if (!isSimpleReference(receiver)) return undefined;
424
+ if (!isSimpleReference(receiver)) {
425
+ return undefined;
426
+ }
425
427
 
426
428
  const m = matchLengthMinus(other, receiverText);
427
429
 
@@ -435,11 +437,15 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
435
437
  if (args.length === 1) {
436
438
  const [start] = args;
437
439
 
438
- if (start === undefined) return undefined;
440
+ if (start === undefined) {
441
+ return undefined;
442
+ }
439
443
 
440
444
  const n = asNonNegativeIntegerLiteral(start);
441
445
 
442
- if (n !== undefined) return normalizeCountedOp('skip', n);
446
+ if (n !== undefined) {
447
+ return normalizeCountedOp('skip', n);
448
+ }
443
449
 
444
450
  const negated = asNegatedPositiveIntegerLiteral(start);
445
451
 
@@ -461,7 +467,9 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
461
467
 
462
468
  const n = asNonNegativeIntegerLiteral(end);
463
469
 
464
- if (n !== undefined) return normalizeCountedOp('take', n);
470
+ if (n !== undefined) {
471
+ return normalizeCountedOp('take', n);
472
+ }
465
473
 
466
474
  const negated = asNegatedPositiveIntegerLiteral(end);
467
475
 
@@ -469,7 +477,9 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
469
477
  return normalizeCountedOp('skipLast', negated);
470
478
  }
471
479
 
472
- if (!isSimpleReference(receiver)) return undefined;
480
+ if (!isSimpleReference(receiver)) {
481
+ return undefined;
482
+ }
473
483
 
474
484
  const m = matchLengthMinus(end, sourceCode.getText(receiver));
475
485
 
@@ -487,12 +497,16 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
487
497
  if (args.length === 1) {
488
498
  const [start] = args;
489
499
 
490
- if (start === undefined) return undefined;
500
+ if (start === undefined) {
501
+ return undefined;
502
+ }
491
503
 
492
504
  const n = asNonNegativeIntegerLiteral(start);
493
505
 
494
506
  // `xs.toSpliced(N)` removes everything from index N on → take N.
495
- if (n !== undefined) return normalizeCountedOp('take', n);
507
+ if (n !== undefined) {
508
+ return normalizeCountedOp('take', n);
509
+ }
496
510
 
497
511
  const negated = asNegatedPositiveIntegerLiteral(start);
498
512
 
@@ -516,12 +530,16 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
516
530
  // `xs.toSpliced(0, N)` removes the first N elements → skip N.
517
531
  const n = asNonNegativeIntegerLiteral(deleteCount);
518
532
 
519
- if (n !== undefined) return normalizeCountedOp('skip', n);
533
+ if (n !== undefined) {
534
+ return normalizeCountedOp('skip', n);
535
+ }
520
536
 
521
537
  // `xs.toSpliced(0, xs.length - N)` keeps the last N → takeLast N.
522
538
  // (Note: `xs.toSpliced(0, -N)` clamps the delete count to 0 and is a
523
539
  // plain copy, so it is deliberately NOT treated as takeLast.)
524
- if (!isSimpleReference(receiver)) return undefined;
540
+ if (!isSimpleReference(receiver)) {
541
+ return undefined;
542
+ }
525
543
 
526
544
  const m = matchLengthMinus(deleteCount, receiverText);
527
545
 
@@ -649,7 +667,9 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
649
667
 
650
668
  // The receiver must be an array or tuple (not a string / typed array
651
669
  // / other object that happens to share the method name).
652
- if (!isArrayOrTupleType(getTypeOf(receiver))) return;
670
+ if (!isArrayOrTupleType(getTypeOf(receiver))) {
671
+ return;
672
+ }
653
673
 
654
674
  const receiverText = sourceCode.getText(receiver);
655
675
 
@@ -657,7 +677,9 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
657
677
  case 'slice': {
658
678
  const op = classifySliceArgs(node.arguments, receiver);
659
679
 
660
- if (op !== undefined) report(node, op, toArgText(receiver));
680
+ if (op !== undefined) {
681
+ report(node, op, toArgText(receiver));
682
+ }
661
683
 
662
684
  return;
663
685
  }
@@ -669,7 +691,9 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
669
691
  receiverText,
670
692
  );
671
693
 
672
- if (op !== undefined) report(node, op, toArgText(receiver));
694
+ if (op !== undefined) {
695
+ report(node, op, toArgText(receiver));
696
+ }
673
697
 
674
698
  return;
675
699
  }
@@ -683,7 +707,9 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
683
707
 
684
708
  const op = classifyFilterCallback(callback, receiver, receiverText);
685
709
 
686
- if (op !== undefined) report(node, op, toArgText(receiver));
710
+ if (op !== undefined) {
711
+ report(node, op, toArgText(receiver));
712
+ }
687
713
 
688
714
  return;
689
715
  }
@@ -735,7 +761,9 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
735
761
  ArrayExpression: (node) => {
736
762
  // `[item, ...xs]` → `Arr.toUnshifted(xs, item)`,
737
763
  // `[...xs, item]` → `Arr.toPushed(xs, item)`.
738
- if (node.elements.length !== 2) return;
764
+ if (node.elements.length !== 2) {
765
+ return;
766
+ }
739
767
 
740
768
  const [first, second] = node.elements;
741
769
 
@@ -760,11 +788,15 @@ export const preferCanonicalArraySlicing: TSESLint.RuleModule<
760
788
  // `spread`, `item`, and `fn` are set together (all from the same
761
789
  // tuple), so checking `spread` also guarantees the others are
762
790
  // defined.
763
- if (spread === undefined) return;
791
+ if (spread === undefined) {
792
+ return;
793
+ }
764
794
 
765
795
  // Spreading a non-array iterable (`[v, ...someSet]`) is a genuine
766
796
  // conversion, not an element addition to an array.
767
- if (!isArrayOrTupleType(getTypeOf(spread.argument))) return;
797
+ if (!isArrayOrTupleType(getTypeOf(spread.argument))) {
798
+ return;
799
+ }
768
800
 
769
801
  report(
770
802
  node,
@@ -145,20 +145,26 @@ export const preferCanonicalLengthCast: TSESLint.RuleModule<
145
145
  'Arr',
146
146
  );
147
147
 
148
- if (arrLocalName === undefined) return {};
148
+ if (arrLocalName === undefined) {
149
+ return {};
150
+ }
149
151
 
150
152
  return {
151
153
  CallExpression: (node) => {
152
154
  const castName = getCastName(node, arrLocalName);
153
155
 
154
- if (castName === undefined) return;
156
+ if (castName === undefined) {
157
+ return;
158
+ }
155
159
 
156
160
  const rewrite = CAST_REWRITES.find(
157
161
  (candidate) =>
158
162
  candidate.cast === castName && matchesBounds(node, candidate),
159
163
  );
160
164
 
161
- if (rewrite === undefined) return;
165
+ if (rewrite === undefined) {
166
+ return;
167
+ }
162
168
 
163
169
  const boundsText = node.arguments
164
170
  .slice(0, rewrite.bounds.length)
@@ -238,7 +244,9 @@ const matchesBounds = (
238
244
  return rewrite.bounds.every((matcher, index) => {
239
245
  const value = bounds[index];
240
246
 
241
- if (value === undefined) return false;
247
+ if (value === undefined) {
248
+ return false;
249
+ }
242
250
 
243
251
  switch (matcher) {
244
252
  case 'anyLength':
@@ -277,9 +285,9 @@ const dropBoundsFix = (
277
285
 
278
286
  const next = node.arguments[index + 1];
279
287
 
280
- if (rewrite.keep.includes(index)) return [];
281
-
282
- return dropped === undefined || next === undefined
288
+ return dropped === undefined ||
289
+ next === undefined ||
290
+ rewrite.keep.includes(index)
283
291
  ? []
284
292
  : [fixer.removeRange([dropped.range[0], next.range[0]])];
285
293
  });
@@ -124,7 +124,9 @@ export const preferCanonicalLengthGuard: TSESLint.RuleModule<
124
124
  rule.create(context),
125
125
  );
126
126
 
127
- if (arrLocalName === undefined) return mergeVisitors(comparisonVisitors);
127
+ if (arrLocalName === undefined) {
128
+ return mergeVisitors(comparisonVisitors);
129
+ }
128
130
 
129
131
  return mergeVisitors([
130
132
  ...comparisonVisitors,
@@ -132,7 +134,9 @@ export const preferCanonicalLengthGuard: TSESLint.RuleModule<
132
134
  CallExpression: (node) => {
133
135
  const guardName = getGuardName(node, arrLocalName);
134
136
 
135
- if (guardName === undefined) return;
137
+ if (guardName === undefined) {
138
+ return;
139
+ }
136
140
 
137
141
  const rewrite = GUARD_REWRITES.find(
138
142
  (entry) => entry.guard === guardName,
@@ -145,7 +149,9 @@ export const preferCanonicalLengthGuard: TSESLint.RuleModule<
145
149
  // The array is the last argument; the bounds precede it.
146
150
  const array = node.arguments[rewrite.bounds.length];
147
151
 
148
- if (array === undefined) return;
152
+ if (array === undefined) {
153
+ return;
154
+ }
149
155
 
150
156
  const arrayText = sourceCode.getText(array);
151
157
 
@@ -185,7 +191,9 @@ const mergeVisitors = (
185
191
 
186
192
  for (const visitor of visitors) {
187
193
  for (const [selector, handler] of Object.entries(visitor)) {
188
- if (typeof handler !== 'function') continue;
194
+ if (typeof handler !== 'function') {
195
+ continue;
196
+ }
189
197
 
190
198
  const mut_handlers = mut_merged[selector] ?? [];
191
199
 
@@ -97,7 +97,9 @@ export const preferComparisonOverNullishGuard: TSESLint.RuleModule<
97
97
 
98
98
  return {
99
99
  CallExpression: (node) => {
100
- if (node.arguments.length !== 1) return;
100
+ if (node.arguments.length !== 1) {
101
+ return;
102
+ }
101
103
 
102
104
  const argument = node.arguments[0];
103
105
 
@@ -110,11 +112,15 @@ export const preferComparisonOverNullishGuard: TSESLint.RuleModule<
110
112
 
111
113
  const resolved = resolveGuard(node.callee);
112
114
 
113
- if (resolved === undefined) return;
115
+ if (resolved === undefined) {
116
+ return;
117
+ }
114
118
 
115
119
  const spec = COMPARISON_GUARDS[resolved.canonicalName];
116
120
 
117
- if (spec === undefined) return;
121
+ if (spec === undefined) {
122
+ return;
123
+ }
118
124
 
119
125
  const argRaw = sourceCode.getText(argument);
120
126
 
@@ -45,7 +45,9 @@ export const preferIsNonNullObject: TSESLint.RuleModule<MessageIds, Options> = {
45
45
  LogicalExpression: (node) => {
46
46
  const identifierName = getNonNullObjectIdentifierName(node);
47
47
 
48
- if (identifierName === undefined) return;
48
+ if (identifierName === undefined) {
49
+ return;
50
+ }
49
51
 
50
52
  mut_nodesToFix.push({ node, identifierName });
51
53
  },
@@ -89,57 +91,59 @@ export const preferIsNonNullObject: TSESLint.RuleModule<MessageIds, Options> = {
89
91
  const getNonNullObjectIdentifierName = (
90
92
  node: DeepReadonly<TSESTree.LogicalExpression>,
91
93
  ): string | undefined => {
92
- if (node.operator !== '&&') return undefined;
94
+ if (node.operator !== '&&') {
95
+ return undefined;
96
+ }
93
97
 
94
98
  const leftIdentifierName = getTypeofObjectIdentifierName(node.left);
95
99
 
96
100
  const rightIdentifierName = getNonNullCheckIdentifierName(node.right);
97
101
 
98
- if (leftIdentifierName === undefined) return undefined;
99
-
100
- if (rightIdentifierName === undefined) return undefined;
101
-
102
- if (leftIdentifierName !== rightIdentifierName) return undefined;
103
-
104
- return leftIdentifierName;
102
+ return leftIdentifierName === undefined ||
103
+ rightIdentifierName === undefined ||
104
+ leftIdentifierName !== rightIdentifierName
105
+ ? undefined
106
+ : leftIdentifierName;
105
107
  };
106
108
 
107
109
  const getTypeofObjectIdentifierName = (
108
110
  node: DeepReadonly<TSESTree.Expression>,
109
111
  ): string | undefined => {
110
- if (node.type !== AST_NODE_TYPES.BinaryExpression) return undefined;
112
+ if (node.type !== AST_NODE_TYPES.BinaryExpression) {
113
+ return undefined;
114
+ }
111
115
 
112
- if (node.operator !== '===') return undefined;
116
+ if (node.operator !== '===') {
117
+ return undefined;
118
+ }
113
119
 
114
120
  const { left, right } = node;
115
121
 
116
- if (left.type !== AST_NODE_TYPES.UnaryExpression) return undefined;
117
-
118
- if (left.operator !== 'typeof') return undefined;
119
-
120
- if (right.type !== AST_NODE_TYPES.Literal) return undefined;
121
-
122
- if (right.value !== 'object') return undefined;
123
-
124
- if (left.argument.type !== AST_NODE_TYPES.Identifier) return undefined;
125
-
126
- return left.argument.name;
122
+ return left.type !== AST_NODE_TYPES.UnaryExpression ||
123
+ left.operator !== 'typeof' ||
124
+ right.type !== AST_NODE_TYPES.Literal ||
125
+ right.value !== 'object' ||
126
+ left.argument.type !== AST_NODE_TYPES.Identifier
127
+ ? undefined
128
+ : left.argument.name;
127
129
  };
128
130
 
129
131
  const getNonNullCheckIdentifierName = (
130
132
  node: DeepReadonly<TSESTree.Expression>,
131
133
  ): string | undefined => {
132
- if (node.type !== AST_NODE_TYPES.BinaryExpression) return undefined;
134
+ if (node.type !== AST_NODE_TYPES.BinaryExpression) {
135
+ return undefined;
136
+ }
133
137
 
134
- if (node.operator !== '!==') return undefined;
138
+ if (node.operator !== '!==') {
139
+ return undefined;
140
+ }
135
141
 
136
142
  const { left, right } = node;
137
143
 
138
- if (left.type !== AST_NODE_TYPES.Identifier) return undefined;
139
-
140
- if (right.type !== AST_NODE_TYPES.Literal) return undefined;
141
-
142
- if (right.value !== null) return undefined;
143
-
144
- return left.name;
144
+ return left.type !== AST_NODE_TYPES.Identifier ||
145
+ right.type !== AST_NODE_TYPES.Literal ||
146
+ right.value !== null
147
+ ? undefined
148
+ : left.name;
145
149
  };
@@ -54,7 +54,9 @@ export const preferIsRecordAndHasKey: TSESLint.RuleModule<MessageIds, Options> =
54
54
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
55
55
  expression: TSESTree.Expression,
56
56
  ): boolean => {
57
- if (checker === undefined) return false;
57
+ if (checker === undefined) {
58
+ return false;
59
+ }
58
60
 
59
61
  const tsNode = services?.esTreeNodeToTSNodeMap?.get(expression);
60
62
 
@@ -84,13 +86,17 @@ export const preferIsRecordAndHasKey: TSESLint.RuleModule<MessageIds, Options> =
84
86
  }
85
87
 
86
88
  // Check arguments: Object.hasOwn(obj, key)
87
- if (node.arguments.length !== 2) return;
89
+ if (node.arguments.length !== 2) {
90
+ return;
91
+ }
88
92
 
89
93
  const objArg = node.arguments[0];
90
94
 
91
95
  const keyArg = node.arguments[1];
92
96
 
93
- if (objArg === undefined || keyArg === undefined) return;
97
+ if (objArg === undefined || keyArg === undefined) {
98
+ return;
99
+ }
94
100
 
95
101
  // Type guard: ensure arguments are Expressions (not SpreadElement)
96
102
  if (
@@ -109,14 +115,18 @@ export const preferIsRecordAndHasKey: TSESLint.RuleModule<MessageIds, Options> =
109
115
 
110
116
  // Handle key in obj
111
117
  BinaryExpression: (node) => {
112
- if (node.operator !== 'in') return;
118
+ if (node.operator !== 'in') {
119
+ return;
120
+ }
113
121
 
114
122
  const keyExpression = node.left;
115
123
 
116
124
  const objExpression = node.right;
117
125
 
118
126
  // Type guard: ensure keyExpression is Expression (not PrivateIdentifier)
119
- if (keyExpression.type === AST_NODE_TYPES.PrivateIdentifier) return;
127
+ if (keyExpression.type === AST_NODE_TYPES.PrivateIdentifier) {
128
+ return;
129
+ }
120
130
 
121
131
  mut_nodesToFix.push({
122
132
  node,