@e18e/eslint-plugin 0.0.1

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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +95 -0
  3. package/lib/configs/modernization.d.ts +2 -0
  4. package/lib/configs/modernization.js +17 -0
  5. package/lib/configs/module-replacements.d.ts +2 -0
  6. package/lib/configs/module-replacements.js +8 -0
  7. package/lib/configs/performance-improvements.d.ts +2 -0
  8. package/lib/configs/performance-improvements.js +9 -0
  9. package/lib/configs/recommended.d.ts +2 -0
  10. package/lib/configs/recommended.js +18 -0
  11. package/lib/main.d.ts +3 -0
  12. package/lib/main.js +48 -0
  13. package/lib/rules/no-indexof-equality.d.ts +2 -0
  14. package/lib/rules/no-indexof-equality.js +90 -0
  15. package/lib/rules/prefer-array-at.d.ts +2 -0
  16. package/lib/rules/prefer-array-at.js +58 -0
  17. package/lib/rules/prefer-array-fill.d.ts +2 -0
  18. package/lib/rules/prefer-array-fill.js +120 -0
  19. package/lib/rules/prefer-array-from-map.d.ts +2 -0
  20. package/lib/rules/prefer-array-from-map.js +57 -0
  21. package/lib/rules/prefer-array-to-reversed.d.ts +2 -0
  22. package/lib/rules/prefer-array-to-reversed.js +42 -0
  23. package/lib/rules/prefer-array-to-sorted.d.ts +2 -0
  24. package/lib/rules/prefer-array-to-sorted.js +43 -0
  25. package/lib/rules/prefer-array-to-spliced.d.ts +2 -0
  26. package/lib/rules/prefer-array-to-spliced.js +43 -0
  27. package/lib/rules/prefer-exponentiation-operator.d.ts +2 -0
  28. package/lib/rules/prefer-exponentiation-operator.js +42 -0
  29. package/lib/rules/prefer-includes.d.ts +2 -0
  30. package/lib/rules/prefer-includes.js +131 -0
  31. package/lib/rules/prefer-nullish-coalescing.d.ts +2 -0
  32. package/lib/rules/prefer-nullish-coalescing.js +131 -0
  33. package/lib/rules/prefer-object-has-own.d.ts +2 -0
  34. package/lib/rules/prefer-object-has-own.js +71 -0
  35. package/lib/rules/prefer-optimized-indexof.d.ts +2 -0
  36. package/lib/rules/prefer-optimized-indexof.js +90 -0
  37. package/lib/rules/prefer-settimeout-args.d.ts +2 -0
  38. package/lib/rules/prefer-settimeout-args.js +175 -0
  39. package/lib/rules/prefer-spread-syntax.d.ts +2 -0
  40. package/lib/rules/prefer-spread-syntax.js +109 -0
  41. package/lib/rules/prefer-timer-args.d.ts +2 -0
  42. package/lib/rules/prefer-timer-args.js +176 -0
  43. package/lib/rules/prefer-url-canparse.d.ts +2 -0
  44. package/lib/rules/prefer-url-canparse.js +139 -0
  45. package/lib/test/setup.d.ts +1 -0
  46. package/lib/test/setup.js +10 -0
  47. package/lib/utils/ast.d.ts +15 -0
  48. package/lib/utils/ast.js +47 -0
  49. package/lib/utils/typescript.d.ts +14 -0
  50. package/lib/utils/typescript.js +6 -0
  51. package/package.json +56 -0
@@ -0,0 +1,43 @@
1
+ import { getArrayFromCopyPattern, formatArguments } from '../utils/ast.js';
2
+ export const preferArrayToSorted = {
3
+ meta: {
4
+ type: 'suggestion',
5
+ docs: {
6
+ description: 'Prefer Array.prototype.toSorted() over copying and sorting arrays',
7
+ recommended: true
8
+ },
9
+ fixable: 'code',
10
+ schema: [],
11
+ messages: {
12
+ preferToSorted: 'Use {{array}}.toSorted() instead of copying and sorting'
13
+ }
14
+ },
15
+ create(context) {
16
+ const sourceCode = context.sourceCode;
17
+ return {
18
+ CallExpression(node) {
19
+ if (node.callee.type !== 'MemberExpression' ||
20
+ node.callee.property.type !== 'Identifier' ||
21
+ node.callee.property.name !== 'sort') {
22
+ return;
23
+ }
24
+ const sortCallee = node.callee.object;
25
+ const arrayNode = getArrayFromCopyPattern(sortCallee);
26
+ if (arrayNode) {
27
+ const arrayText = sourceCode.getText(arrayNode);
28
+ const argsText = formatArguments(node.arguments, sourceCode);
29
+ context.report({
30
+ node,
31
+ messageId: 'preferToSorted',
32
+ data: {
33
+ array: arrayText
34
+ },
35
+ fix(fixer) {
36
+ return fixer.replaceText(node, `${arrayText}.toSorted(${argsText})`);
37
+ }
38
+ });
39
+ }
40
+ }
41
+ };
42
+ }
43
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const preferArrayToSpliced: Rule.RuleModule;
@@ -0,0 +1,43 @@
1
+ import { getArrayFromCopyPattern, formatArguments } from '../utils/ast.js';
2
+ export const preferArrayToSpliced = {
3
+ meta: {
4
+ type: 'suggestion',
5
+ docs: {
6
+ description: 'Prefer Array.prototype.toSpliced() over copying and splicing arrays',
7
+ recommended: true
8
+ },
9
+ fixable: 'code',
10
+ schema: [],
11
+ messages: {
12
+ preferToSpliced: 'Use {{array}}.toSpliced() instead of copying and splicing'
13
+ }
14
+ },
15
+ create(context) {
16
+ const sourceCode = context.sourceCode;
17
+ return {
18
+ CallExpression(node) {
19
+ if (node.callee.type !== 'MemberExpression' ||
20
+ node.callee.property.type !== 'Identifier' ||
21
+ node.callee.property.name !== 'splice') {
22
+ return;
23
+ }
24
+ const spliceCallee = node.callee.object;
25
+ const arrayNode = getArrayFromCopyPattern(spliceCallee);
26
+ if (arrayNode) {
27
+ const arrayText = sourceCode.getText(arrayNode);
28
+ const argsText = formatArguments(node.arguments, sourceCode);
29
+ context.report({
30
+ node,
31
+ messageId: 'preferToSpliced',
32
+ data: {
33
+ array: arrayText
34
+ },
35
+ fix(fixer) {
36
+ return fixer.replaceText(node, `${arrayText}.toSpliced(${argsText})`);
37
+ }
38
+ });
39
+ }
40
+ }
41
+ };
42
+ }
43
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const preferExponentiationOperator: Rule.RuleModule;
@@ -0,0 +1,42 @@
1
+ export const preferExponentiationOperator = {
2
+ meta: {
3
+ type: 'suggestion',
4
+ docs: {
5
+ description: 'Prefer the exponentiation operator ** over Math.pow()',
6
+ recommended: true
7
+ },
8
+ fixable: 'code',
9
+ schema: [],
10
+ messages: {
11
+ preferExponentiation: 'Use the ** operator instead of Math.pow()'
12
+ }
13
+ },
14
+ create(context) {
15
+ const sourceCode = context.sourceCode;
16
+ return {
17
+ CallExpression(node) {
18
+ if (node.callee.type !== 'MemberExpression' ||
19
+ node.callee.object.type !== 'Identifier' ||
20
+ node.callee.object.name !== 'Math' ||
21
+ node.callee.property.type !== 'Identifier' ||
22
+ node.callee.property.name !== 'pow') {
23
+ return;
24
+ }
25
+ const base = node.arguments[0];
26
+ const exponent = node.arguments[1];
27
+ if (!base || !exponent || node.arguments.length !== 2) {
28
+ return;
29
+ }
30
+ context.report({
31
+ node,
32
+ messageId: 'preferExponentiation',
33
+ fix(fixer) {
34
+ const baseText = sourceCode.getText(base);
35
+ const exponentText = sourceCode.getText(exponent);
36
+ return fixer.replaceText(node, `(${baseText}) ** (${exponentText})`);
37
+ }
38
+ });
39
+ }
40
+ };
41
+ }
42
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const preferIncludes: Rule.RuleModule;
@@ -0,0 +1,131 @@
1
+ function isIndexOfCall(node) {
2
+ return (node.type === 'CallExpression' &&
3
+ node.callee.type === 'MemberExpression' &&
4
+ node.callee.property.type === 'Identifier' &&
5
+ node.callee.property.name === 'indexOf' &&
6
+ node.arguments.length >= 1);
7
+ }
8
+ function isNegativeOne(node) {
9
+ return (node.type === 'UnaryExpression' &&
10
+ node.operator === '-' &&
11
+ node.argument.type === 'Literal' &&
12
+ node.argument.value === 1);
13
+ }
14
+ function isZero(node) {
15
+ return node.type === 'Literal' && node.value === 0;
16
+ }
17
+ function reportIndexOf(context, node, indexOfCall, shouldNegate) {
18
+ const sourceCode = context.sourceCode;
19
+ const arrayText = sourceCode.getText(indexOfCall.callee.type === 'MemberExpression'
20
+ ? indexOfCall.callee.object
21
+ : indexOfCall.callee);
22
+ const argsText = indexOfCall.arguments
23
+ .map((arg) => sourceCode.getText(arg))
24
+ .join(', ');
25
+ const replacement = shouldNegate
26
+ ? `!${arrayText}.includes(${argsText})`
27
+ : `${arrayText}.includes(${argsText})`;
28
+ context.report({
29
+ node,
30
+ messageId: 'preferIncludes',
31
+ fix(fixer) {
32
+ return fixer.replaceText(node, replacement);
33
+ }
34
+ });
35
+ }
36
+ function checkBinaryExpression(node, context) {
37
+ const { left, right, operator } = node;
38
+ if (left.type === 'PrivateIdentifier') {
39
+ return;
40
+ }
41
+ let indexOfCall;
42
+ let constantSide;
43
+ let op = operator;
44
+ if (isIndexOfCall(left)) {
45
+ indexOfCall = left;
46
+ constantSide = right;
47
+ }
48
+ else if (isIndexOfCall(right)) {
49
+ indexOfCall = right;
50
+ constantSide = left;
51
+ if (operator === '<') {
52
+ op = '>';
53
+ }
54
+ else if (operator === '>') {
55
+ op = '<';
56
+ }
57
+ else if (operator === '<=') {
58
+ op = '>=';
59
+ }
60
+ else if (operator === '>=') {
61
+ op = '<=';
62
+ }
63
+ }
64
+ else {
65
+ return;
66
+ }
67
+ if (isNegativeOne(constantSide)) {
68
+ if (op === '!==' || op === '!=' || op === '>') {
69
+ reportIndexOf(context, node, indexOfCall, false);
70
+ return;
71
+ }
72
+ if (op === '===' || op === '==') {
73
+ reportIndexOf(context, node, indexOfCall, true);
74
+ return;
75
+ }
76
+ }
77
+ if (isZero(constantSide)) {
78
+ if (op === '>=') {
79
+ reportIndexOf(context, node, indexOfCall, false);
80
+ return;
81
+ }
82
+ if (op === '<') {
83
+ reportIndexOf(context, node, indexOfCall, true);
84
+ return;
85
+ }
86
+ }
87
+ }
88
+ function checkUnaryExpression(node, context) {
89
+ if (node.operator === '~' && isIndexOfCall(node.argument)) {
90
+ reportIndexOf(context, node, node.argument, false);
91
+ return;
92
+ }
93
+ if (node.operator === '!' &&
94
+ node.argument.type === 'UnaryExpression' &&
95
+ node.argument.operator === '~' &&
96
+ isIndexOfCall(node.argument.argument)) {
97
+ reportIndexOf(context, node, node.argument.argument, true);
98
+ return;
99
+ }
100
+ }
101
+ export const preferIncludes = {
102
+ meta: {
103
+ type: 'suggestion',
104
+ docs: {
105
+ description: 'Prefer .includes() over indexOf() comparisons for arrays and strings',
106
+ recommended: true
107
+ },
108
+ fixable: 'code',
109
+ schema: [],
110
+ messages: {
111
+ preferIncludes: 'Use .includes() instead of indexOf() comparison'
112
+ }
113
+ },
114
+ create(context) {
115
+ return {
116
+ BinaryExpression(node) {
117
+ checkBinaryExpression(node, context);
118
+ },
119
+ UnaryExpression(node) {
120
+ // Skip ~ if it's inside !~ (the parent will handle it)
121
+ if (node.operator === '~' && node.parent) {
122
+ if (node.parent.type === 'UnaryExpression' &&
123
+ node.parent.operator === '!') {
124
+ return;
125
+ }
126
+ }
127
+ checkUnaryExpression(node, context);
128
+ }
129
+ };
130
+ }
131
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const preferNullishCoalescing: Rule.RuleModule;
@@ -0,0 +1,131 @@
1
+ function areExpressionsEquivalent(sourceCode, expr1, expr2) {
2
+ return sourceCode.getText(expr1) === sourceCode.getText(expr2);
3
+ }
4
+ function isNullLiteral(node) {
5
+ return node.type === 'Literal' && node.value === null;
6
+ }
7
+ function isUndefinedIdentifier(node) {
8
+ return node.type === 'Identifier' && node.name === 'undefined';
9
+ }
10
+ function isNullishCheck(sourceCode, expr) {
11
+ if (expr.type === 'BinaryExpression' &&
12
+ expr.left.type !== 'PrivateIdentifier' &&
13
+ isNullLiteral(expr.right) &&
14
+ (expr.operator === '==' || expr.operator === '!=')) {
15
+ return { value: expr.left, checksForNullish: expr.operator === '==' };
16
+ }
17
+ if (expr.type === 'LogicalExpression' &&
18
+ expr.left.type === 'BinaryExpression' &&
19
+ expr.right.type === 'BinaryExpression' &&
20
+ expr.left.left.type !== 'PrivateIdentifier' &&
21
+ expr.right.left.type !== 'PrivateIdentifier') {
22
+ const leftOp = expr.left.operator;
23
+ const rightOp = expr.right.operator;
24
+ const leftRight = expr.left.right;
25
+ const rightRight = expr.right.right;
26
+ const leftLeft = expr.left.left;
27
+ const rightLeft = expr.right.left;
28
+ const leftIsNull = isNullLiteral(leftRight);
29
+ const leftIsUndefined = isUndefinedIdentifier(leftRight);
30
+ const rightIsNull = isNullLiteral(rightRight);
31
+ const rightIsUndefined = isUndefinedIdentifier(rightRight);
32
+ if (!areExpressionsEquivalent(sourceCode, leftLeft, rightLeft)) {
33
+ return null;
34
+ }
35
+ if ((leftIsNull && rightIsUndefined) || (leftIsUndefined && rightIsNull)) {
36
+ if (expr.operator === '||' && leftOp === '===' && rightOp === '===') {
37
+ return { value: leftLeft, checksForNullish: true };
38
+ }
39
+ if (expr.operator === '&&' && leftOp === '!==' && rightOp === '!==') {
40
+ return { value: leftLeft, checksForNullish: false };
41
+ }
42
+ }
43
+ }
44
+ return null;
45
+ }
46
+ export const preferNullishCoalescing = {
47
+ meta: {
48
+ type: 'suggestion',
49
+ docs: {
50
+ description: 'Prefer nullish coalescing operator (?? and ??=) over verbose null checks',
51
+ recommended: true
52
+ },
53
+ fixable: 'code',
54
+ schema: [],
55
+ messages: {
56
+ preferNullishCoalescing: 'Use nullish coalescing operator (??) instead of verbose null check',
57
+ preferNullishCoalescingAssignment: 'Use nullish coalescing assignment (??=) instead of verbose null check'
58
+ }
59
+ },
60
+ create(context) {
61
+ const sourceCode = context.sourceCode;
62
+ return {
63
+ ConditionalExpression(node) {
64
+ const checkResult = isNullishCheck(sourceCode, node.test);
65
+ if (checkResult) {
66
+ const { value, checksForNullish } = checkResult;
67
+ const compareNode = checksForNullish
68
+ ? node.alternate
69
+ : node.consequent;
70
+ const defaultNode = checksForNullish
71
+ ? node.consequent
72
+ : node.alternate;
73
+ if (areExpressionsEquivalent(sourceCode, value, compareNode)) {
74
+ context.report({
75
+ node,
76
+ messageId: 'preferNullishCoalescing',
77
+ fix(fixer) {
78
+ const valueText = sourceCode.getText(value);
79
+ const defaultText = sourceCode.getText(defaultNode);
80
+ return fixer.replaceText(node, `${valueText} ?? ${defaultText}`);
81
+ }
82
+ });
83
+ }
84
+ }
85
+ },
86
+ IfStatement(node) {
87
+ if (node.alternate) {
88
+ return;
89
+ }
90
+ let body = null;
91
+ if (node.consequent.type === 'BlockStatement') {
92
+ const blockStmt = node.consequent;
93
+ if (blockStmt.body.length !== 1) {
94
+ return;
95
+ }
96
+ if (blockStmt.body[0]?.type === 'ExpressionStatement') {
97
+ body = blockStmt.body[0];
98
+ }
99
+ }
100
+ else if (node.consequent.type === 'ExpressionStatement') {
101
+ body = node.consequent;
102
+ }
103
+ if (!body || body.expression.type !== 'AssignmentExpression') {
104
+ return;
105
+ }
106
+ const assignment = body.expression;
107
+ if (assignment.operator !== '=') {
108
+ return;
109
+ }
110
+ if (assignment.left.type !== 'Identifier' &&
111
+ assignment.left.type !== 'MemberExpression') {
112
+ return;
113
+ }
114
+ const checkResult = isNullishCheck(sourceCode, node.test);
115
+ if (checkResult &&
116
+ checkResult.checksForNullish &&
117
+ areExpressionsEquivalent(sourceCode, checkResult.value, assignment.left)) {
118
+ context.report({
119
+ node,
120
+ messageId: 'preferNullishCoalescingAssignment',
121
+ fix(fixer) {
122
+ const leftText = sourceCode.getText(assignment.left);
123
+ const rightText = sourceCode.getText(assignment.right);
124
+ return fixer.replaceText(node, `${leftText} ??= ${rightText}`);
125
+ }
126
+ });
127
+ }
128
+ }
129
+ };
130
+ }
131
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const preferObjectHasOwn: Rule.RuleModule;
@@ -0,0 +1,71 @@
1
+ function getObjectPrototypeHasOwnPropertyArgs(node) {
2
+ if (node.callee.type === 'MemberExpression' &&
3
+ node.callee.property.type === 'Identifier' &&
4
+ node.callee.property.name === 'call') {
5
+ const hasOwnPropertyExpr = node.callee.object;
6
+ if (hasOwnPropertyExpr.type === 'MemberExpression' &&
7
+ hasOwnPropertyExpr.property.type === 'Identifier' &&
8
+ hasOwnPropertyExpr.property.name === 'hasOwnProperty' &&
9
+ hasOwnPropertyExpr.object.type === 'MemberExpression' &&
10
+ hasOwnPropertyExpr.object.property.type === 'Identifier' &&
11
+ hasOwnPropertyExpr.object.property.name === 'prototype' &&
12
+ hasOwnPropertyExpr.object.object.type === 'Identifier' &&
13
+ hasOwnPropertyExpr.object.object.name === 'Object') {
14
+ return node.arguments;
15
+ }
16
+ }
17
+ return null;
18
+ }
19
+ export const preferObjectHasOwn = {
20
+ meta: {
21
+ type: 'suggestion',
22
+ docs: {
23
+ description: 'Prefer Object.hasOwn() over Object.prototype.hasOwnProperty.call() and obj.hasOwnProperty()',
24
+ recommended: true
25
+ },
26
+ fixable: 'code',
27
+ schema: [],
28
+ messages: {
29
+ preferObjectHasOwn: 'Use Object.hasOwn() instead of hasOwnProperty'
30
+ }
31
+ },
32
+ create(context) {
33
+ const sourceCode = context.sourceCode;
34
+ return {
35
+ CallExpression(node) {
36
+ // Check for Object.prototype.hasOwnProperty.call(obj, prop)
37
+ const prototypeArgs = getObjectPrototypeHasOwnPropertyArgs(node);
38
+ if (prototypeArgs && prototypeArgs.length === 2) {
39
+ const [object, property] = prototypeArgs;
40
+ const objectText = sourceCode.getText(object);
41
+ const propertyText = sourceCode.getText(property);
42
+ context.report({
43
+ node,
44
+ messageId: 'preferObjectHasOwn',
45
+ fix(fixer) {
46
+ return fixer.replaceText(node, `Object.hasOwn(${objectText}, ${propertyText})`);
47
+ }
48
+ });
49
+ return;
50
+ }
51
+ // Check for obj.hasOwnProperty(prop)
52
+ if (node.callee.type === 'MemberExpression' &&
53
+ node.callee.property.type === 'Identifier' &&
54
+ node.callee.property.name === 'hasOwnProperty' &&
55
+ node.arguments.length === 1) {
56
+ const object = node.callee.object;
57
+ const property = node.arguments[0];
58
+ const objectText = sourceCode.getText(object);
59
+ const propertyText = sourceCode.getText(property);
60
+ context.report({
61
+ node,
62
+ messageId: 'preferObjectHasOwn',
63
+ fix(fixer) {
64
+ return fixer.replaceText(node, `Object.hasOwn(${objectText}, ${propertyText})`);
65
+ }
66
+ });
67
+ }
68
+ }
69
+ };
70
+ }
71
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const preferOptimizedIndexof: Rule.RuleModule;
@@ -0,0 +1,90 @@
1
+ import { getTypedParserServices } from '../utils/typescript.js';
2
+ export const preferOptimizedIndexof = {
3
+ meta: {
4
+ type: 'suggestion',
5
+ docs: {
6
+ description: 'Prefer optimized alternatives to `indexOf()` equality checks',
7
+ recommended: false
8
+ },
9
+ fixable: 'code',
10
+ schema: [],
11
+ messages: {
12
+ preferDirectAccess: 'Use direct array access `{{array}}[{{index}}] === {{item}}` instead of `indexOf() === {{index}}`',
13
+ preferStartsWith: 'Use `.startsWith()` instead of `indexOf() === 0` for strings'
14
+ }
15
+ },
16
+ create(context) {
17
+ const sourceCode = context.sourceCode;
18
+ const services = getTypedParserServices(context);
19
+ const checker = services.program.getTypeChecker();
20
+ return {
21
+ BinaryExpression(node) {
22
+ if (node.operator !== '===' && node.operator !== '==') {
23
+ return;
24
+ }
25
+ let indexOfCall;
26
+ let compareIndex;
27
+ if (node.left.type === 'CallExpression' &&
28
+ node.right.type === 'Literal' &&
29
+ typeof node.right.value === 'number' &&
30
+ node.right.value >= 0) {
31
+ indexOfCall = node.left;
32
+ compareIndex = node.right.value;
33
+ }
34
+ else if (node.right.type === 'CallExpression' &&
35
+ node.left.type === 'Literal' &&
36
+ typeof node.left.value === 'number' &&
37
+ node.left.value >= 0) {
38
+ indexOfCall = node.right;
39
+ compareIndex = node.left.value;
40
+ }
41
+ if (!indexOfCall || compareIndex === undefined) {
42
+ return;
43
+ }
44
+ if (indexOfCall.callee.type !== 'MemberExpression' ||
45
+ indexOfCall.callee.property.type !== 'Identifier' ||
46
+ indexOfCall.callee.property.name !== 'indexOf') {
47
+ return;
48
+ }
49
+ if (indexOfCall.arguments.length !== 1) {
50
+ return;
51
+ }
52
+ const objectNode = indexOfCall.callee.object;
53
+ const searchArg = indexOfCall.arguments[0];
54
+ const type = services.getTypeAtLocation(objectNode);
55
+ if (!type) {
56
+ return;
57
+ }
58
+ const objectText = sourceCode.getText(objectNode);
59
+ const searchText = sourceCode.getText(searchArg);
60
+ const stringType = checker.getStringType();
61
+ if (checker.isTypeAssignableTo(type, stringType)) {
62
+ if (compareIndex === 0) {
63
+ context.report({
64
+ node,
65
+ messageId: 'preferStartsWith',
66
+ fix(fixer) {
67
+ return fixer.replaceText(node, `${objectText}.startsWith(${searchText})`);
68
+ }
69
+ });
70
+ }
71
+ return;
72
+ }
73
+ if (checker.isArrayType(type)) {
74
+ context.report({
75
+ node,
76
+ messageId: 'preferDirectAccess',
77
+ data: {
78
+ array: objectText,
79
+ item: searchText,
80
+ index: String(compareIndex)
81
+ },
82
+ fix(fixer) {
83
+ return fixer.replaceText(node, `${objectText}[${compareIndex}] === ${searchText}`);
84
+ }
85
+ });
86
+ }
87
+ }
88
+ };
89
+ }
90
+ };
@@ -0,0 +1,2 @@
1
+ import type { Rule } from 'eslint';
2
+ export declare const preferSetTimeoutArgs: Rule.RuleModule;