@typescript-eslint/eslint-plugin 8.67.1-alpha.20 → 8.67.1-alpha.22

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.
@@ -19,6 +19,11 @@ export declare function getEnumLiterals(type: ts.Type): ts.LiteralType[];
19
19
  * - T extends Fruit --> [Fruit]
20
20
  */
21
21
  export declare function getEnumTypes(typeChecker: ts.TypeChecker, type: ts.Type): ts.Type[];
22
+ /**
23
+ * @returns Whether two types compare unsafely because an enum value is being
24
+ * compared against a non-enum value of the same primitive kind.
25
+ */
26
+ export declare function isMismatchedEnumComparisonTypes(typeChecker: ts.TypeChecker, leftType: ts.Type, rightType: ts.Type): boolean;
22
27
  /**
23
28
  * Returns the enum key that matches the given literal node, or null if none
24
29
  * match. For example:
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.getEnumLiterals = getEnumLiterals;
37
37
  exports.getEnumTypes = getEnumTypes;
38
+ exports.isMismatchedEnumComparisonTypes = isMismatchedEnumComparisonTypes;
38
39
  exports.getEnumKeyForLiteral = getEnumKeyForLiteral;
39
40
  const tsutils = __importStar(require("ts-api-utils"));
40
41
  const ts = __importStar(require("typescript"));
@@ -81,6 +82,72 @@ function getEnumLiterals(type) {
81
82
  function getEnumTypes(typeChecker, type) {
82
83
  return getEnumLiterals(type).map(type => getBaseEnumType(typeChecker, type));
83
84
  }
85
+ /**
86
+ * @returns Whether two types compare unsafely because an enum value is being
87
+ * compared against a non-enum value of the same primitive kind.
88
+ */
89
+ function isMismatchedEnumComparisonTypes(typeChecker, leftType, rightType) {
90
+ // Allow comparisons that don't have anything to do with enums:
91
+ //
92
+ // ```ts
93
+ // 1 === 2;
94
+ // ```
95
+ const leftEnumTypes = getEnumTypes(typeChecker, leftType);
96
+ const rightEnumTypes = new Set(getEnumTypes(typeChecker, rightType));
97
+ if (leftEnumTypes.length === 0 && rightEnumTypes.size === 0) {
98
+ return false;
99
+ }
100
+ // Allow comparisons that share an enum type:
101
+ //
102
+ // ```ts
103
+ // Fruit.Apple === Fruit.Banana;
104
+ // ```
105
+ for (const leftEnumType of leftEnumTypes) {
106
+ if (rightEnumTypes.has(leftEnumType)) {
107
+ return false;
108
+ }
109
+ }
110
+ // We need to split the type into the union type parts in order to find
111
+ // valid enum comparisons like:
112
+ //
113
+ // ```ts
114
+ // declare const something: Fruit | Vegetable;
115
+ // something === Fruit.Apple;
116
+ // ```
117
+ const leftTypeParts = tsutils.unionConstituents(leftType);
118
+ const rightTypeParts = tsutils.unionConstituents(rightType);
119
+ // If a type exists in both sides, we consider this comparison safe:
120
+ //
121
+ // ```ts
122
+ // declare const fruit: Fruit.Apple | 0;
123
+ // fruit === 0;
124
+ // ```
125
+ for (const leftTypePart of leftTypeParts) {
126
+ if (rightTypeParts.includes(leftTypePart)) {
127
+ return false;
128
+ }
129
+ }
130
+ return (typeViolates(leftTypeParts, rightType) ||
131
+ typeViolates(rightTypeParts, leftType));
132
+ }
133
+ /**
134
+ * @returns Whether the right type is an unsafe comparison against any left type.
135
+ */
136
+ function typeViolates(leftTypeParts, rightType) {
137
+ const leftEnumValueTypes = new Set(leftTypeParts.map(getEnumValueType));
138
+ return ((leftEnumValueTypes.has(ts.TypeFlags.Number) && (0, util_1.isNumberLike)(rightType)) ||
139
+ (leftEnumValueTypes.has(ts.TypeFlags.String) && (0, util_1.isStringLike)(rightType)));
140
+ }
141
+ /**
142
+ * @returns What type a type's enum value is (number or string), if either.
143
+ */
144
+ function getEnumValueType(type) {
145
+ return tsutils.isTypeFlagSet(type, ts.TypeFlags.EnumLike)
146
+ ? tsutils.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral)
147
+ ? ts.TypeFlags.Number
148
+ : ts.TypeFlags.String
149
+ : undefined;
150
+ }
84
151
  /**
85
152
  * Returns the enum key that matches the given literal node, or null if none
86
153
  * match. For example:
@@ -72,15 +72,19 @@ exports.default = (0, util_1.createRule)({
72
72
  return;
73
73
  }
74
74
  const scope = context.sourceCode.getScope(node);
75
- const mergedWithClassDeclaration = scope.set
75
+ const mergedWithOtherDeclaration = scope.set
76
76
  .get(node.id.name)
77
- ?.defs.some(def => def.node.type === utils_1.AST_NODE_TYPES.ClassDeclaration);
77
+ ?.defs.some(def => def.node !== node &&
78
+ (def.node.type === utils_1.AST_NODE_TYPES.ClassDeclaration ||
79
+ def.node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration));
80
+ const isDefaultExport = node.parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration;
81
+ const shouldSuggest = !mergedWithOtherDeclaration && !isDefaultExport;
78
82
  if (extend.length === 0) {
79
83
  context.report({
80
84
  node: node.id,
81
85
  messageId: 'noEmptyInterface',
82
86
  data: { option: 'allowInterfaces' },
83
- ...(!mergedWithClassDeclaration && {
87
+ ...(shouldSuggest && {
84
88
  suggest: ['object', 'unknown'].map(replacement => ({
85
89
  messageId: 'replaceEmptyInterface',
86
90
  data: { replacement },
@@ -99,7 +103,7 @@ exports.default = (0, util_1.createRule)({
99
103
  context.report({
100
104
  node: node.id,
101
105
  messageId: 'noEmptyInterfaceWithSuper',
102
- ...(!mergedWithClassDeclaration && {
106
+ ...(shouldSuggest && {
103
107
  suggest: [
104
108
  {
105
109
  messageId: 'replaceEmptyInterfaceWithSuper',
@@ -64,18 +64,6 @@ exports.default = (0, util_1.createRule)({
64
64
  create(context) {
65
65
  const services = (0, util_1.getParserServices)(context);
66
66
  const checker = services.program.getTypeChecker();
67
- function isStringLike(type) {
68
- return (0, util_1.isTypeFlagSet)(type, ts.TypeFlags.StringLike);
69
- }
70
- function isUnderlyingTypeString(type) {
71
- if (type.isUnion()) {
72
- return type.types.every(isStringLike);
73
- }
74
- if (type.isIntersection()) {
75
- return type.types.some(isStringLike);
76
- }
77
- return isStringLike(type);
78
- }
79
67
  function isEnumMemberType(type) {
80
68
  return tsutils.typeConstituents(type).some(t => {
81
69
  const symbol = t.getSymbol();
@@ -315,7 +303,7 @@ exports.default = (0, util_1.createRule)({
315
303
  if (isTrivialInterpolation(node) &&
316
304
  !hasCommentsBetweenQuasi(node.quasis[0], node.quasis[1])) {
317
305
  const { constraintType } = (0, util_1.getConstraintInfo)(checker, services.getTypeAtLocation(node.expressions[0]));
318
- if (constraintType && isUnderlyingTypeString(constraintType)) {
306
+ if (constraintType && (0, util_1.isStringLike)(constraintType)) {
319
307
  reportSingleInterpolation(node);
320
308
  return;
321
309
  }
@@ -331,7 +319,7 @@ exports.default = (0, util_1.createRule)({
331
319
  const { constraintType, isTypeParameter } = (0, util_1.getConstraintInfo)(checker, services.getTypeAtLocation(node.types[0]));
332
320
  if (constraintType &&
333
321
  !isTypeParameter &&
334
- isUnderlyingTypeString(constraintType) &&
322
+ (0, util_1.isStringLike)(constraintType) &&
335
323
  !isEnumMemberType(constraintType)) {
336
324
  reportSingleInterpolation(node);
337
325
  return;
@@ -37,96 +37,6 @@ const utils_1 = require("@typescript-eslint/utils");
37
37
  const tsutils = __importStar(require("ts-api-utils"));
38
38
  const ts = __importStar(require("typescript"));
39
39
  const util_1 = require("../util");
40
- var RestTypeKind;
41
- (function (RestTypeKind) {
42
- RestTypeKind[RestTypeKind["Array"] = 0] = "Array";
43
- RestTypeKind[RestTypeKind["Tuple"] = 1] = "Tuple";
44
- RestTypeKind[RestTypeKind["Other"] = 2] = "Other";
45
- })(RestTypeKind || (RestTypeKind = {}));
46
- class FunctionSignature {
47
- paramTypes;
48
- restType;
49
- hasConsumedArguments = false;
50
- parameterTypeIndex = 0;
51
- constructor(paramTypes, restType) {
52
- this.paramTypes = paramTypes;
53
- this.restType = restType;
54
- }
55
- static create(checker, tsNode) {
56
- const signature = checker.getResolvedSignature(tsNode);
57
- if (!signature) {
58
- return null;
59
- }
60
- const paramTypes = [];
61
- let restType = null;
62
- const parameters = signature.getParameters();
63
- for (let i = 0; i < parameters.length; i += 1) {
64
- const param = parameters[i];
65
- const type = checker.getTypeOfSymbolAtLocation(param, tsNode);
66
- const decl = param.getDeclarations()?.[0];
67
- if (decl && (0, util_1.isRestParameterDeclaration)(decl)) {
68
- // is a rest param
69
- if (checker.isArrayType(type)) {
70
- restType = {
71
- type: checker.getTypeArguments(type)[0],
72
- index: i,
73
- kind: RestTypeKind.Array,
74
- };
75
- }
76
- else if (checker.isTupleType(type)) {
77
- restType = {
78
- index: i,
79
- kind: RestTypeKind.Tuple,
80
- typeArguments: checker.getTypeArguments(type),
81
- };
82
- }
83
- else {
84
- restType = {
85
- type,
86
- index: i,
87
- kind: RestTypeKind.Other,
88
- };
89
- }
90
- break;
91
- }
92
- paramTypes.push(type);
93
- }
94
- return new this(paramTypes, restType);
95
- }
96
- consumeRemainingArguments() {
97
- this.hasConsumedArguments = true;
98
- }
99
- getNextParameterType() {
100
- const index = this.parameterTypeIndex;
101
- this.parameterTypeIndex += 1;
102
- if (index >= this.paramTypes.length || this.hasConsumedArguments) {
103
- if (this.restType == null) {
104
- return null;
105
- }
106
- switch (this.restType.kind) {
107
- case RestTypeKind.Tuple: {
108
- const typeArguments = this.restType.typeArguments;
109
- if (this.hasConsumedArguments) {
110
- // all types consumed by a rest - just assume it's the last type
111
- // there is one edge case where this is wrong, but we ignore it because
112
- // it's rare and really complicated to handle
113
- // eg: function foo(...a: [number, ...string[], number])
114
- return typeArguments[typeArguments.length - 1];
115
- }
116
- const typeIndex = index - this.restType.index;
117
- if (typeIndex >= typeArguments.length) {
118
- return typeArguments[typeArguments.length - 1];
119
- }
120
- return typeArguments[typeIndex];
121
- }
122
- case RestTypeKind.Array:
123
- case RestTypeKind.Other:
124
- return this.restType.type;
125
- }
126
- }
127
- return this.paramTypes[index];
128
- }
129
- }
130
40
  exports.default = (0, util_1.createRule)({
131
41
  name: 'no-unsafe-argument',
132
42
  meta: {
@@ -176,7 +86,7 @@ exports.default = (0, util_1.createRule)({
176
86
  return;
177
87
  }
178
88
  const tsNode = services.esTreeNodeToTSNodeMap.get(node);
179
- const signature = (0, util_1.nullThrows)(FunctionSignature.create(checker, tsNode), 'Expected to a signature resolved');
89
+ const signature = util_1.FunctionSignature.create(checker, tsNode);
180
90
  if (node.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression) {
181
91
  // Consumes the first parameter (TemplateStringsArray) of the function called with TaggedTemplateExpression.
182
92
  signature.getNextParameterType();
@@ -1,74 +1,7 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
- const tsutils = __importStar(require("ts-api-utils"));
37
- const ts = __importStar(require("typescript"));
38
3
  const util_1 = require("../util");
39
4
  const shared_1 = require("./enum-utils/shared");
40
- /**
41
- * @returns Whether the right type is an unsafe comparison against any left type.
42
- */
43
- function typeViolates(leftTypeParts, rightType) {
44
- const leftEnumValueTypes = new Set(leftTypeParts.map(getEnumValueType));
45
- return ((leftEnumValueTypes.has(ts.TypeFlags.Number) && isNumberLike(rightType)) ||
46
- (leftEnumValueTypes.has(ts.TypeFlags.String) && isStringLike(rightType)));
47
- }
48
- function isNumberLike(type) {
49
- return tsutils
50
- .unionConstituents(type)
51
- .every(unionPart => tsutils
52
- .intersectionConstituents(unionPart)
53
- .some(intersectionPart => tsutils.isTypeFlagSet(intersectionPart, ts.TypeFlags.Number | ts.TypeFlags.NumberLike)));
54
- }
55
- function isStringLike(type) {
56
- return tsutils
57
- .unionConstituents(type)
58
- .every(unionPart => tsutils
59
- .intersectionConstituents(unionPart)
60
- .some(intersectionPart => tsutils.isTypeFlagSet(intersectionPart, ts.TypeFlags.String | ts.TypeFlags.StringLike)));
61
- }
62
- /**
63
- * @returns What type a type's enum value is (number or string), if either.
64
- */
65
- function getEnumValueType(type) {
66
- return tsutils.isTypeFlagSet(type, ts.TypeFlags.EnumLike)
67
- ? tsutils.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral)
68
- ? ts.TypeFlags.Number
69
- : ts.TypeFlags.String
70
- : undefined;
71
- }
72
5
  exports.default = (0, util_1.createRule)({
73
6
  name: 'no-unsafe-enum-comparison',
74
7
  meta: {
@@ -90,55 +23,11 @@ exports.default = (0, util_1.createRule)({
90
23
  create(context) {
91
24
  const parserServices = (0, util_1.getParserServices)(context);
92
25
  const typeChecker = parserServices.program.getTypeChecker();
93
- function isMismatchedComparison(leftType, rightType) {
94
- // Allow comparisons that don't have anything to do with enums:
95
- //
96
- // ```ts
97
- // 1 === 2;
98
- // ```
99
- const leftEnumTypes = (0, shared_1.getEnumTypes)(typeChecker, leftType);
100
- const rightEnumTypes = new Set((0, shared_1.getEnumTypes)(typeChecker, rightType));
101
- if (leftEnumTypes.length === 0 && rightEnumTypes.size === 0) {
102
- return false;
103
- }
104
- // Allow comparisons that share an enum type:
105
- //
106
- // ```ts
107
- // Fruit.Apple === Fruit.Banana;
108
- // ```
109
- for (const leftEnumType of leftEnumTypes) {
110
- if (rightEnumTypes.has(leftEnumType)) {
111
- return false;
112
- }
113
- }
114
- // We need to split the type into the union type parts in order to find
115
- // valid enum comparisons like:
116
- //
117
- // ```ts
118
- // declare const something: Fruit | Vegetable;
119
- // something === Fruit.Apple;
120
- // ```
121
- const leftTypeParts = tsutils.unionConstituents(leftType);
122
- const rightTypeParts = tsutils.unionConstituents(rightType);
123
- // If a type exists in both sides, we consider this comparison safe:
124
- //
125
- // ```ts
126
- // declare const fruit: Fruit.Apple | 0;
127
- // fruit === 0;
128
- // ```
129
- for (const leftTypePart of leftTypeParts) {
130
- if (rightTypeParts.includes(leftTypePart)) {
131
- return false;
132
- }
133
- }
134
- return (typeViolates(leftTypeParts, rightType) ||
135
- typeViolates(rightTypeParts, leftType));
136
- }
137
26
  return {
138
27
  'BinaryExpression[operator=/^[<>!=]?={0,2}$/]'(node) {
139
28
  const leftType = parserServices.getTypeAtLocation(node.left);
140
29
  const rightType = parserServices.getTypeAtLocation(node.right);
141
- if (isMismatchedComparison(leftType, rightType)) {
30
+ if ((0, shared_1.isMismatchedEnumComparisonTypes)(typeChecker, leftType, rightType)) {
142
31
  context.report({
143
32
  node,
144
33
  messageId: 'mismatchedCondition',
@@ -180,7 +69,7 @@ exports.default = (0, util_1.createRule)({
180
69
  const { parent } = node;
181
70
  const leftType = parserServices.getTypeAtLocation(parent.discriminant);
182
71
  const rightType = parserServices.getTypeAtLocation(node.test);
183
- if (isMismatchedComparison(leftType, rightType)) {
72
+ if ((0, shared_1.isMismatchedEnumComparisonTypes)(typeChecker, leftType, rightType)) {
184
73
  context.report({
185
74
  node,
186
75
  messageId: 'mismatchedCase',
@@ -0,0 +1,15 @@
1
+ import * as ts from 'typescript';
2
+ /**
3
+ * Tracks checking the parameters of a single function signature.
4
+ * This allows rules to "consume" parameters and check for unsafe comparisons.
5
+ */
6
+ export declare class FunctionSignature {
7
+ private readonly paramTypes;
8
+ private readonly restType;
9
+ private hasConsumedArguments;
10
+ private parameterTypeIndex;
11
+ private constructor();
12
+ static create(checker: ts.TypeChecker, tsNode: ts.CallLikeExpression): FunctionSignature;
13
+ consumeRemainingArguments(): void;
14
+ getNextParameterType(): ts.Type | null;
15
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FunctionSignature = void 0;
37
+ const utils_1 = require("@typescript-eslint/utils");
38
+ const ts = __importStar(require("typescript"));
39
+ const misc_1 = require("./misc");
40
+ const { nullThrows } = utils_1.ESLintUtils;
41
+ var RestTypeKind;
42
+ (function (RestTypeKind) {
43
+ RestTypeKind[RestTypeKind["Array"] = 0] = "Array";
44
+ RestTypeKind[RestTypeKind["Other"] = 1] = "Other";
45
+ RestTypeKind[RestTypeKind["Tuple"] = 2] = "Tuple";
46
+ })(RestTypeKind || (RestTypeKind = {}));
47
+ /**
48
+ * Tracks checking the parameters of a single function signature.
49
+ * This allows rules to "consume" parameters and check for unsafe comparisons.
50
+ */
51
+ class FunctionSignature {
52
+ paramTypes;
53
+ restType;
54
+ hasConsumedArguments = false;
55
+ parameterTypeIndex = 0;
56
+ constructor(paramTypes, restType) {
57
+ this.paramTypes = paramTypes;
58
+ this.restType = restType;
59
+ }
60
+ static create(checker, tsNode) {
61
+ // getResolvedSignature only returns undefined for nodes outside the parse
62
+ // tree, and tsNode always comes from the AST node map.
63
+ const signature = nullThrows(checker.getResolvedSignature(tsNode), 'Expected the call-like node to resolve to a signature.');
64
+ const paramTypes = [];
65
+ let restType = null;
66
+ const parameters = signature.getParameters();
67
+ for (let index = 0; index < parameters.length; index += 1) {
68
+ const param = parameters[index];
69
+ const declaration = param.getDeclarations()?.[0];
70
+ const type = checker.getTypeOfSymbolAtLocation(param, tsNode);
71
+ const constrainedType = checker.getBaseConstraintOfType(type) ?? type;
72
+ if (declaration && (0, misc_1.isRestParameterDeclaration)(declaration)) {
73
+ if (checker.isTupleType(constrainedType)) {
74
+ restType = {
75
+ index,
76
+ kind: RestTypeKind.Tuple,
77
+ typeArguments: checker.getTypeArguments(constrainedType),
78
+ };
79
+ }
80
+ else {
81
+ const elementType = checker.getIndexTypeOfType(constrainedType, ts.IndexKind.Number);
82
+ restType = elementType
83
+ ? { index, kind: RestTypeKind.Array, type: elementType }
84
+ : { index, kind: RestTypeKind.Other, type: constrainedType };
85
+ }
86
+ break;
87
+ }
88
+ paramTypes.push(type);
89
+ }
90
+ return new FunctionSignature(paramTypes, restType);
91
+ }
92
+ consumeRemainingArguments() {
93
+ this.hasConsumedArguments = true;
94
+ }
95
+ getNextParameterType() {
96
+ const index = this.parameterTypeIndex;
97
+ this.parameterTypeIndex += 1;
98
+ if (index >= this.paramTypes.length || this.hasConsumedArguments) {
99
+ if (this.restType == null) {
100
+ return null;
101
+ }
102
+ switch (this.restType.kind) {
103
+ case RestTypeKind.Tuple: {
104
+ const { typeArguments } = this.restType;
105
+ if (this.hasConsumedArguments) {
106
+ return typeArguments[typeArguments.length - 1];
107
+ }
108
+ const typeIndex = index - this.restType.index;
109
+ if (typeIndex >= typeArguments.length) {
110
+ return typeArguments[typeArguments.length - 1];
111
+ }
112
+ return typeArguments[typeIndex];
113
+ }
114
+ case RestTypeKind.Array:
115
+ case RestTypeKind.Other:
116
+ return this.restType.type;
117
+ }
118
+ }
119
+ return this.paramTypes[index];
120
+ }
121
+ }
122
+ exports.FunctionSignature = FunctionSignature;
123
+ //# sourceMappingURL=FunctionSignature.js.map
@@ -1,6 +1,8 @@
1
1
  import type { ParserServicesWithTypeInformation } from '@typescript-eslint/utils';
2
2
  import type { InterfaceType, Type } from 'typescript';
3
3
  export declare function hasBaseTypes(type: Type): type is InterfaceType;
4
+ export declare function isNumberLike(type: Type): boolean;
5
+ export declare function isStringLike(type: Type): boolean;
4
6
  /**
5
7
  * Recursively checks if a type or any of its base types matches the provided
6
8
  * matcher function.
@@ -34,6 +34,8 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.hasBaseTypes = hasBaseTypes;
37
+ exports.isNumberLike = isNumberLike;
38
+ exports.isStringLike = isStringLike;
37
39
  exports.matchesTypeOrBaseType = matchesTypeOrBaseType;
38
40
  const ts_api_utils_1 = require("ts-api-utils");
39
41
  const tsutils = __importStar(require("ts-api-utils"));
@@ -53,6 +55,20 @@ function hasBaseTypes(type) {
53
55
  return ((0, ts_api_utils_1.isObjectType)(type) &&
54
56
  (0, ts_api_utils_1.isObjectFlagSet)(type, ts.ObjectFlags.Interface | ts.ObjectFlags.Class));
55
57
  }
58
+ function isNumberLike(type) {
59
+ return tsutils
60
+ .unionConstituents(type)
61
+ .every(unionPart => tsutils
62
+ .intersectionConstituents(unionPart)
63
+ .some(intersectionPart => tsutils.isTypeFlagSet(intersectionPart, ts.TypeFlags.NumberLike)));
64
+ }
65
+ function isStringLike(type) {
66
+ return tsutils
67
+ .unionConstituents(type)
68
+ .every(unionPart => tsutils
69
+ .intersectionConstituents(unionPart)
70
+ .some(intersectionPart => tsutils.isTypeFlagSet(intersectionPart, ts.TypeFlags.StringLike)));
71
+ }
56
72
  /**
57
73
  * Recursively checks if a type or any of its base types matches the provided
58
74
  * matcher function.
@@ -3,6 +3,7 @@ export * from './astUtils';
3
3
  export * from './baseTypeUtils';
4
4
  export * from './collectUnusedVariables';
5
5
  export * from './createRule';
6
+ export * from './FunctionSignature';
6
7
  export * from './getBaseTypesOfClassMember';
7
8
  export * from './getFixOrSuggest';
8
9
  export * from './getFunctionHeadLoc';
@@ -20,6 +20,7 @@ __exportStar(require("./astUtils"), exports);
20
20
  __exportStar(require("./baseTypeUtils"), exports);
21
21
  __exportStar(require("./collectUnusedVariables"), exports);
22
22
  __exportStar(require("./createRule"), exports);
23
+ __exportStar(require("./FunctionSignature"), exports);
23
24
  __exportStar(require("./getBaseTypesOfClassMember"), exports);
24
25
  __exportStar(require("./getFixOrSuggest"), exports);
25
26
  __exportStar(require("./getFunctionHeadLoc"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typescript-eslint/eslint-plugin",
3
- "version": "8.67.1-alpha.20",
3
+ "version": "8.67.1-alpha.22",
4
4
  "description": "TypeScript plugin for ESLint",
5
5
  "files": [
6
6
  "dist",
@@ -47,10 +47,10 @@
47
47
  ],
48
48
  "dependencies": {
49
49
  "@eslint-community/regexpp": "^4.12.2",
50
- "@typescript-eslint/scope-manager": "8.67.1-alpha.20",
51
- "@typescript-eslint/type-utils": "8.67.1-alpha.20",
52
- "@typescript-eslint/utils": "8.67.1-alpha.20",
53
- "@typescript-eslint/visitor-keys": "8.67.1-alpha.20",
50
+ "@typescript-eslint/scope-manager": "8.67.1-alpha.22",
51
+ "@typescript-eslint/type-utils": "8.67.1-alpha.22",
52
+ "@typescript-eslint/utils": "8.67.1-alpha.22",
53
+ "@typescript-eslint/visitor-keys": "8.67.1-alpha.22",
54
54
  "ignore": "^7.0.5",
55
55
  "natural-compare": "^1.4.0",
56
56
  "ts-api-utils": "^2.5.0"
@@ -60,8 +60,8 @@
60
60
  "@types/mdast": "^4.0.4",
61
61
  "@types/natural-compare": "^1.4.3",
62
62
  "@types/react": "^18.3.21",
63
- "@typescript-eslint/rule-schema-to-typescript-types": "8.67.1-alpha.20",
64
- "@typescript-eslint/rule-tester": "8.67.1-alpha.20",
63
+ "@typescript-eslint/rule-schema-to-typescript-types": "8.67.1-alpha.22",
64
+ "@typescript-eslint/rule-tester": "8.67.1-alpha.22",
65
65
  "@typescript/native": "npm:typescript@^7.0.2",
66
66
  "@vitest/coverage-v8": "^4.0.18",
67
67
  "ajv": "^6.12.6",
@@ -81,7 +81,7 @@
81
81
  "vitest": "^4.0.18"
82
82
  },
83
83
  "peerDependencies": {
84
- "@typescript-eslint/parser": "^8.67.1-alpha.20",
84
+ "@typescript-eslint/parser": "^8.67.1-alpha.22",
85
85
  "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
86
86
  "typescript": ">=4.8.4 <6.1.0"
87
87
  },