@typescript-eslint/eslint-plugin 8.47.1-alpha.1 → 8.47.1-alpha.11
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/dist/configs/eslint-recommended-raw.js +6 -1
- package/dist/index.d.ts +1 -1
- package/dist/raw-plugin.d.ts +1 -1
- package/dist/rules/consistent-generic-constructors.js +17 -1
- package/dist/rules/explicit-member-accessibility.js +1 -7
- package/dist/rules/index.d.ts +1 -1
- package/dist/rules/no-redundant-type-constituents.d.ts +1 -1
- package/dist/rules/no-redundant-type-constituents.js +398 -258
- package/dist/rules/no-unnecessary-parameter-property-assignment.js +0 -1
- package/dist/rules/parameter-properties.js +1 -7
- package/dist/rules/restrict-template-expressions.d.ts +1 -1
- package/dist/util/class-scope-analyzer/extractComputedName.js +4 -14
- package/dist/util/collectUnusedVariables.js +3 -7
- package/package.json +8 -8
|
@@ -21,8 +21,13 @@ const config = (style) => ({
|
|
|
21
21
|
'no-dupe-keys': 'off', // ts(1117)
|
|
22
22
|
'no-func-assign': 'off', // ts(2630)
|
|
23
23
|
'no-import-assign': 'off', // ts(2632) & ts(2540)
|
|
24
|
-
// TODO - remove this once we no longer support ESLint v8
|
|
25
24
|
'no-new-native-nonconstructor': 'off', // ts(7009)
|
|
25
|
+
// "no-new-symbol" was deprecated in ESLint 9.0.0 and will be removed in
|
|
26
|
+
// ESLint v11.0.0. See:
|
|
27
|
+
// https://eslint.org/docs/latest/rules/no-new-symbol
|
|
28
|
+
// We need to keep the rule disabled until TSESLint drops support for
|
|
29
|
+
// ESlint 8. See:
|
|
30
|
+
// https://github.com/typescript-eslint/typescript-eslint/pull/8895
|
|
26
31
|
'no-new-symbol': 'off', // ts(7009)
|
|
27
32
|
'no-obj-calls': 'off', // ts(2349)
|
|
28
33
|
'no-redeclare': 'off', // ts(2451)
|
package/dist/index.d.ts
CHANGED
|
@@ -764,7 +764,7 @@ declare const _default: {
|
|
|
764
764
|
'no-non-null-asserted-optional-chain': import("@typescript-eslint/utils/ts-eslint").RuleModule<"suggestRemovingNonNull" | "noNonNullOptionalChain", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
765
765
|
'no-non-null-assertion': import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./rules/no-non-null-assertion").MessageIds, [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
766
766
|
'no-redeclare': import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./rules/no-redeclare").MessageIds, import("./rules/no-redeclare").Options, import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
767
|
-
'no-redundant-type-constituents': import("@typescript-eslint/utils/ts-eslint").RuleModule<"overrides" | "errorTypeOverrides" | "
|
|
767
|
+
'no-redundant-type-constituents': import("@typescript-eslint/utils/ts-eslint").RuleModule<"overrides" | "errorTypeOverrides" | "overridden" | "typeOverridden", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
768
768
|
'no-require-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"noRequireImports", import("./rules/no-require-imports").Options, import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
769
769
|
'no-restricted-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"everything" | "everythingWithCustomMessage" | "importName" | "importNameWithCustomMessage" | "path" | "pathWithCustomMessage" | "patterns" | "patternWithCustomMessage", [import("eslint/lib/rules/no-restricted-imports").ObjectOfPathsAndPatterns] | import("eslint/lib/rules/no-restricted-imports").ArrayOfStringOrObject, import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
770
770
|
'no-restricted-types': import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./rules/no-restricted-types").MessageIds, import("./rules/no-restricted-types").Options, import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
package/dist/raw-plugin.d.ts
CHANGED
|
@@ -787,7 +787,7 @@ declare const _default: {
|
|
|
787
787
|
'no-non-null-asserted-optional-chain': TSESLint.RuleModule<"suggestRemovingNonNull" | "noNonNullOptionalChain", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
|
|
788
788
|
'no-non-null-assertion': TSESLint.RuleModule<import("./rules/no-non-null-assertion").MessageIds, [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
|
|
789
789
|
'no-redeclare': TSESLint.RuleModule<import("./rules/no-redeclare").MessageIds, import("./rules/no-redeclare").Options, import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
|
|
790
|
-
'no-redundant-type-constituents': TSESLint.RuleModule<"overrides" | "errorTypeOverrides" | "
|
|
790
|
+
'no-redundant-type-constituents': TSESLint.RuleModule<"overrides" | "errorTypeOverrides" | "overridden" | "typeOverridden", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
|
|
791
791
|
'no-require-imports': TSESLint.RuleModule<"noRequireImports", import("./rules/no-require-imports").Options, import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
|
|
792
792
|
'no-restricted-imports': TSESLint.RuleModule<"everything" | "everythingWithCustomMessage" | "importName" | "importNameWithCustomMessage" | "path" | "pathWithCustomMessage" | "patterns" | "patternWithCustomMessage", [import("eslint/lib/rules/no-restricted-imports").ObjectOfPathsAndPatterns] | import("eslint/lib/rules/no-restricted-imports").ArrayOfStringOrObject, import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
|
|
793
793
|
'no-restricted-types': TSESLint.RuleModule<import("./rules/no-restricted-types").MessageIds, import("./rules/no-restricted-types").Options, import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
|
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("@typescript-eslint/utils");
|
|
4
4
|
const util_1 = require("../util");
|
|
5
|
+
const builtInArrays = new Set([
|
|
6
|
+
'Float32Array',
|
|
7
|
+
'Float64Array',
|
|
8
|
+
'Int16Array',
|
|
9
|
+
'Int32Array',
|
|
10
|
+
'Int8Array',
|
|
11
|
+
'Uint16Array',
|
|
12
|
+
'Uint32Array',
|
|
13
|
+
'Uint8Array',
|
|
14
|
+
'Uint8ClampedArray',
|
|
15
|
+
]);
|
|
5
16
|
exports.default = (0, util_1.createRule)({
|
|
6
17
|
name: 'consistent-generic-constructors',
|
|
7
18
|
meta: {
|
|
@@ -40,6 +51,10 @@ exports.default = (0, util_1.createRule)({
|
|
|
40
51
|
throw new Error(`Unhandled node type: ${node.type}`);
|
|
41
52
|
}
|
|
42
53
|
}
|
|
54
|
+
function isBuiltInArray(typeName) {
|
|
55
|
+
return (builtInArrays.has(typeName.name) &&
|
|
56
|
+
(0, util_1.isReferenceToGlobalFunction)(typeName.name, typeName, context.sourceCode));
|
|
57
|
+
}
|
|
43
58
|
const [lhsName, rhs] = getLHSRHS();
|
|
44
59
|
const lhs = lhsName.typeAnnotation?.typeAnnotation;
|
|
45
60
|
if (!rhs ||
|
|
@@ -50,7 +65,8 @@ exports.default = (0, util_1.createRule)({
|
|
|
50
65
|
if (lhs &&
|
|
51
66
|
(lhs.type !== utils_1.AST_NODE_TYPES.TSTypeReference ||
|
|
52
67
|
lhs.typeName.type !== utils_1.AST_NODE_TYPES.Identifier ||
|
|
53
|
-
lhs.typeName.name !== rhs.callee.name
|
|
68
|
+
lhs.typeName.name !== rhs.callee.name ||
|
|
69
|
+
isBuiltInArray(lhs.typeName))) {
|
|
54
70
|
return;
|
|
55
71
|
}
|
|
56
72
|
if (mode === 'type-annotation') {
|
|
@@ -255,15 +255,9 @@ exports.default = (0, util_1.createRule)({
|
|
|
255
255
|
*/
|
|
256
256
|
function checkParameterPropertyAccessibilityModifier(node) {
|
|
257
257
|
const nodeType = 'parameter property';
|
|
258
|
-
// HAS to be an identifier or assignment or TSC will throw
|
|
259
|
-
if (node.parameter.type !== utils_1.AST_NODE_TYPES.Identifier &&
|
|
260
|
-
node.parameter.type !== utils_1.AST_NODE_TYPES.AssignmentPattern) {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
258
|
const nodeName = node.parameter.type === utils_1.AST_NODE_TYPES.Identifier
|
|
264
259
|
? node.parameter.name
|
|
265
|
-
:
|
|
266
|
-
node.parameter.left.name;
|
|
260
|
+
: node.parameter.left.name;
|
|
267
261
|
switch (paramPropCheck) {
|
|
268
262
|
case 'explicit': {
|
|
269
263
|
if (!node.accessibility) {
|
package/dist/rules/index.d.ts
CHANGED
|
@@ -92,7 +92,7 @@ declare const rules: {
|
|
|
92
92
|
'no-non-null-asserted-optional-chain': import("@typescript-eslint/utils/ts-eslint").RuleModule<"suggestRemovingNonNull" | "noNonNullOptionalChain", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
93
93
|
'no-non-null-assertion': import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./no-non-null-assertion").MessageIds, [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
94
94
|
'no-redeclare': import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./no-redeclare").MessageIds, import("./no-redeclare").Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
95
|
-
'no-redundant-type-constituents': import("@typescript-eslint/utils/ts-eslint").RuleModule<"overrides" | "errorTypeOverrides" | "
|
|
95
|
+
'no-redundant-type-constituents': import("@typescript-eslint/utils/ts-eslint").RuleModule<"overrides" | "errorTypeOverrides" | "overridden" | "typeOverridden", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
96
96
|
'no-require-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"noRequireImports", import("./no-require-imports").Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
97
97
|
'no-restricted-imports': import("@typescript-eslint/utils/ts-eslint").RuleModule<"everything" | "everythingWithCustomMessage" | "importName" | "importNameWithCustomMessage" | "path" | "pathWithCustomMessage" | "patterns" | "patternWithCustomMessage", [import("eslint/lib/rules/no-restricted-imports").ObjectOfPathsAndPatterns] | import("eslint/lib/rules/no-restricted-imports").ArrayOfStringOrObject, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
98
98
|
'no-restricted-types': import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./no-restricted-types").MessageIds, import("./no-restricted-types").Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"overrides" | "errorTypeOverrides" | "
|
|
1
|
+
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"overrides" | "errorTypeOverrides" | "overridden" | "typeOverridden", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
2
2
|
export default _default;
|
|
@@ -37,47 +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
|
-
const literalToPrimitiveTypeFlags = {
|
|
41
|
-
[ts.TypeFlags.BigIntLiteral]: ts.TypeFlags.BigInt,
|
|
42
|
-
[ts.TypeFlags.BooleanLiteral]: ts.TypeFlags.Boolean,
|
|
43
|
-
[ts.TypeFlags.NumberLiteral]: ts.TypeFlags.Number,
|
|
44
|
-
[ts.TypeFlags.StringLiteral]: ts.TypeFlags.String,
|
|
45
|
-
[ts.TypeFlags.TemplateLiteral]: ts.TypeFlags.String,
|
|
46
|
-
};
|
|
47
|
-
const literalTypeFlags = [
|
|
48
|
-
ts.TypeFlags.BigIntLiteral,
|
|
49
|
-
ts.TypeFlags.BooleanLiteral,
|
|
50
|
-
ts.TypeFlags.NumberLiteral,
|
|
51
|
-
ts.TypeFlags.StringLiteral,
|
|
52
|
-
ts.TypeFlags.TemplateLiteral,
|
|
53
|
-
];
|
|
54
|
-
const primitiveTypeFlags = [
|
|
55
|
-
ts.TypeFlags.BigInt,
|
|
56
|
-
ts.TypeFlags.Boolean,
|
|
57
|
-
ts.TypeFlags.Number,
|
|
58
|
-
ts.TypeFlags.String,
|
|
59
|
-
];
|
|
60
|
-
const primitiveTypeFlagNames = {
|
|
61
|
-
[ts.TypeFlags.BigInt]: 'bigint',
|
|
62
|
-
[ts.TypeFlags.Boolean]: 'boolean',
|
|
63
|
-
[ts.TypeFlags.Number]: 'number',
|
|
64
|
-
[ts.TypeFlags.String]: 'string',
|
|
65
|
-
};
|
|
66
|
-
const primitiveTypeFlagTypes = {
|
|
67
|
-
bigint: ts.TypeFlags.BigIntLiteral,
|
|
68
|
-
boolean: ts.TypeFlags.BooleanLiteral,
|
|
69
|
-
number: ts.TypeFlags.NumberLiteral,
|
|
70
|
-
string: ts.TypeFlags.StringLiteral,
|
|
71
|
-
};
|
|
72
|
-
const keywordNodeTypesToTsTypes = new Map([
|
|
73
|
-
[utils_1.TSESTree.AST_NODE_TYPES.TSAnyKeyword, ts.TypeFlags.Any],
|
|
74
|
-
[utils_1.TSESTree.AST_NODE_TYPES.TSBigIntKeyword, ts.TypeFlags.BigInt],
|
|
75
|
-
[utils_1.TSESTree.AST_NODE_TYPES.TSBooleanKeyword, ts.TypeFlags.Boolean],
|
|
76
|
-
[utils_1.TSESTree.AST_NODE_TYPES.TSNeverKeyword, ts.TypeFlags.Never],
|
|
77
|
-
[utils_1.TSESTree.AST_NODE_TYPES.TSNumberKeyword, ts.TypeFlags.Number],
|
|
78
|
-
[utils_1.TSESTree.AST_NODE_TYPES.TSStringKeyword, ts.TypeFlags.String],
|
|
79
|
-
[utils_1.TSESTree.AST_NODE_TYPES.TSUnknownKeyword, ts.TypeFlags.Unknown],
|
|
80
|
-
]);
|
|
81
40
|
function addToMapGroup(map, key, value) {
|
|
82
41
|
const existing = map.get(key);
|
|
83
42
|
if (existing) {
|
|
@@ -87,88 +46,270 @@ function addToMapGroup(map, key, value) {
|
|
|
87
46
|
map.set(key, [value]);
|
|
88
47
|
}
|
|
89
48
|
}
|
|
90
|
-
function
|
|
91
|
-
if (type.
|
|
92
|
-
return
|
|
49
|
+
function isUnionNodeInsideReturnType(node) {
|
|
50
|
+
if (node.parent.type === utils_1.AST_NODE_TYPES.TSUnionType) {
|
|
51
|
+
return isUnionNodeInsideReturnType(node.parent);
|
|
93
52
|
}
|
|
94
|
-
|
|
95
|
-
|
|
53
|
+
return (node.parent.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation &&
|
|
54
|
+
(0, util_1.isFunctionOrFunctionType)(node.parent.parent));
|
|
55
|
+
}
|
|
56
|
+
function isObjectOrIntersectionType(type) {
|
|
57
|
+
return tsutils.isObjectType(type) || tsutils.isIntersectionType(type);
|
|
58
|
+
}
|
|
59
|
+
function shouldCheckTypeRedundancy(type, checker, depth = 0) {
|
|
60
|
+
if (depth > 10) {
|
|
61
|
+
return false;
|
|
96
62
|
}
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
63
|
+
if (tsutils.isObjectType(type)) {
|
|
64
|
+
const symbol = type.getSymbol();
|
|
65
|
+
if (checker.isArrayLikeType(type)) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
if (!symbol) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const declarations = symbol.getDeclarations();
|
|
72
|
+
const declaration = declarations?.[0];
|
|
73
|
+
if (!declaration) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
if (declaration.kind !== ts.SyntaxKind.TypeLiteral &&
|
|
77
|
+
declaration.kind !== ts.SyntaxKind.InterfaceDeclaration &&
|
|
78
|
+
declaration.kind !== ts.SyntaxKind.MappedType) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
100
81
|
}
|
|
101
|
-
if (
|
|
102
|
-
|
|
82
|
+
if (isObjectOrIntersectionType(type)) {
|
|
83
|
+
const props = type.getProperties();
|
|
84
|
+
for (const prop of props) {
|
|
85
|
+
const type = checker.getTypeOfSymbol(prop);
|
|
86
|
+
if (!shouldCheckTypeRedundancy(type, checker, depth + 1)) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
103
91
|
}
|
|
104
|
-
if (
|
|
105
|
-
return
|
|
92
|
+
if (tsutils.isUnionType(type)) {
|
|
93
|
+
return type.types.every(typePart => shouldCheckTypeRedundancy(typePart, checker, depth));
|
|
106
94
|
}
|
|
107
|
-
|
|
108
|
-
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
function isTargetTypeRedundantInIntersection(sourceType, targetType, checker) {
|
|
98
|
+
if (!shouldCheckTypeRedundancy(sourceType, checker) ||
|
|
99
|
+
!shouldCheckTypeRedundancy(targetType, checker)) {
|
|
100
|
+
return false;
|
|
109
101
|
}
|
|
110
|
-
if (
|
|
111
|
-
|
|
102
|
+
if (tsutils.isUnionType(sourceType)) {
|
|
103
|
+
for (const typePart of sourceType.types) {
|
|
104
|
+
if (!tsutils.isObjectType(typePart)) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const isRedundant = isTargetTypeRedundantInIntersection(typePart, targetType, checker);
|
|
108
|
+
if (!isRedundant) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return checker.isTypeAssignableTo(sourceType, targetType);
|
|
112
113
|
}
|
|
113
|
-
if (
|
|
114
|
-
|
|
114
|
+
if (tsutils.isUnionType(targetType) &&
|
|
115
|
+
!tsutils.isIntrinsicBooleanType(targetType)) {
|
|
116
|
+
for (const typePart of targetType.types) {
|
|
117
|
+
if (!tsutils.isObjectType(typePart)) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const isRedundant = isTargetTypeRedundantInIntersection(sourceType, typePart, checker);
|
|
121
|
+
if (!isRedundant) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return checker.isTypeAssignableTo(sourceType, targetType);
|
|
115
126
|
}
|
|
116
|
-
if (
|
|
117
|
-
|
|
127
|
+
if (checker.isTupleType(targetType)) {
|
|
128
|
+
if (checker.isTupleType(sourceType)) {
|
|
129
|
+
const sourceArguments = sourceType.typeArguments;
|
|
130
|
+
const targetArguments = targetType.typeArguments;
|
|
131
|
+
if (!sourceArguments || !targetArguments) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
if (targetArguments.length !== sourceArguments.length) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
for (let i = 0; i < targetArguments.length; ++i) {
|
|
138
|
+
const sourceTypeArgument = sourceArguments[i];
|
|
139
|
+
const targetTypeArgument = targetArguments[i];
|
|
140
|
+
if (!isTargetTypeRedundantInIntersection(sourceTypeArgument, targetTypeArgument, checker)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
118
147
|
}
|
|
119
|
-
if (
|
|
120
|
-
|
|
148
|
+
if (checker.isArrayType(targetType)) {
|
|
149
|
+
if (checker.isArrayType(sourceType)) {
|
|
150
|
+
const sourceArgumentType = sourceType.typeArguments?.[0];
|
|
151
|
+
const targetArgumentType = targetType.typeArguments?.[0];
|
|
152
|
+
if (!sourceArgumentType || !targetArgumentType) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
return isTargetTypeRedundantInIntersection(sourceArgumentType, targetArgumentType, checker);
|
|
156
|
+
}
|
|
157
|
+
if (checker.isTupleType(sourceType)) {
|
|
158
|
+
const targetArgumentType = targetType.typeArguments?.[0];
|
|
159
|
+
if (!targetArgumentType) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
const sourceArgumentTypes = sourceType.typeArguments;
|
|
163
|
+
if (!sourceArgumentTypes) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
for (const sourceTypeArgument of sourceArgumentTypes) {
|
|
167
|
+
if (!isTargetTypeRedundantInIntersection(sourceTypeArgument, targetArgumentType, checker)) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
return false;
|
|
121
174
|
}
|
|
122
|
-
if (tsutils.
|
|
123
|
-
|
|
175
|
+
if (tsutils.isObjectType(sourceType) && tsutils.isObjectType(targetType)) {
|
|
176
|
+
const sourceProps = sourceType.getProperties();
|
|
177
|
+
const targetProps = targetType.getProperties();
|
|
178
|
+
if (targetProps.length === 0) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
for (const targetProp of targetProps) {
|
|
182
|
+
const sourceProp = sourceProps.find(prop => prop.getName() === targetProp.getName());
|
|
183
|
+
if (!sourceProp) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
const sourcePropType = checker.getTypeOfSymbol(sourceProp);
|
|
187
|
+
const targetPropType = checker.getTypeOfSymbol(targetProp);
|
|
188
|
+
const targetPropTypeIsRedundant = isTargetTypeRedundantInIntersection(sourcePropType, targetPropType, checker);
|
|
189
|
+
if (!targetPropTypeIsRedundant) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
124
194
|
}
|
|
125
|
-
return
|
|
195
|
+
return checker.isTypeAssignableTo(sourceType, targetType);
|
|
126
196
|
}
|
|
127
|
-
function
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
case 'string':
|
|
148
|
-
return JSON.stringify(typeNode.literal.value);
|
|
149
|
-
default:
|
|
150
|
-
return `${typeNode.literal.value}`;
|
|
151
|
-
}
|
|
152
|
-
case utils_1.TSESTree.AST_NODE_TYPES.TemplateLiteral:
|
|
153
|
-
return 'template literal type';
|
|
197
|
+
function isTargetTypeRedundantInUnion(sourceType, targetType, checker) {
|
|
198
|
+
if (!shouldCheckTypeRedundancy(sourceType, checker) ||
|
|
199
|
+
!shouldCheckTypeRedundancy(targetType, checker)) {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
if (tsutils.isUnionType(targetType) &&
|
|
203
|
+
!tsutils.isIntrinsicBooleanType(targetType)) {
|
|
204
|
+
for (const typePart of targetType.types) {
|
|
205
|
+
const isRedundant = isTargetTypeRedundantInUnion(sourceType, typePart, checker);
|
|
206
|
+
if (!isRedundant) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
if (tsutils.isUnionType(sourceType)) {
|
|
213
|
+
for (const typePart of sourceType.types) {
|
|
214
|
+
const isRedundant = isTargetTypeRedundantInUnion(typePart, targetType, checker);
|
|
215
|
+
if (isRedundant) {
|
|
216
|
+
return true;
|
|
154
217
|
}
|
|
218
|
+
}
|
|
219
|
+
return false;
|
|
155
220
|
}
|
|
156
|
-
|
|
221
|
+
if (checker.isTupleType(targetType)) {
|
|
222
|
+
if (checker.isArrayType(sourceType)) {
|
|
223
|
+
const sourceArgumentType = sourceType.typeArguments?.[0];
|
|
224
|
+
if (!sourceArgumentType) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
const targetArguments = targetType.typeArguments;
|
|
228
|
+
if (!targetArguments) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
for (const targetTypeArgument of targetArguments) {
|
|
232
|
+
if (!isTargetTypeRedundantInUnion(sourceArgumentType, targetTypeArgument, checker)) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
if (checker.isTupleType(sourceType)) {
|
|
239
|
+
const sourceArguments = sourceType.typeArguments;
|
|
240
|
+
const targetArguments = targetType.typeArguments;
|
|
241
|
+
if (!sourceArguments || !targetArguments) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
if (targetArguments.length !== sourceArguments.length) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
for (let i = 0; i < targetArguments.length; ++i) {
|
|
248
|
+
const sourceTypeArgument = sourceArguments[i];
|
|
249
|
+
const targetTypeArgument = targetArguments[i];
|
|
250
|
+
if (!isTargetTypeRedundantInUnion(sourceTypeArgument, targetTypeArgument, checker)) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
if (checker.isArrayType(sourceType) && checker.isArrayType(targetType)) {
|
|
259
|
+
const sourceArgumentType = sourceType.typeArguments?.[0];
|
|
260
|
+
const targetArgumentType = targetType.typeArguments?.[0];
|
|
261
|
+
if (!sourceArgumentType || !targetArgumentType) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
return isTargetTypeRedundantInUnion(sourceArgumentType, targetArgumentType, checker);
|
|
265
|
+
}
|
|
266
|
+
if (isObjectOrIntersectionType(sourceType) &&
|
|
267
|
+
isObjectOrIntersectionType(targetType)) {
|
|
268
|
+
const sourceProps = sourceType.getProperties();
|
|
269
|
+
const targetProps = targetType.getProperties();
|
|
270
|
+
if (sourceProps.length !== targetProps.length) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
if (targetProps.length === 0) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
for (const targetProp of targetProps) {
|
|
277
|
+
const sourceProp = sourceProps.find(prop => prop.getName() === targetProp.getName());
|
|
278
|
+
if (!sourceProp) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
const sourcePropType = checker.getTypeOfSymbol(sourceProp);
|
|
282
|
+
const targetPropType = checker.getTypeOfSymbol(targetProp);
|
|
283
|
+
const targetPropTypeIsRedundant = isTargetTypeRedundantInUnion(sourcePropType, targetPropType, checker);
|
|
284
|
+
if (!targetPropTypeIsRedundant) {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
return checker.isTypeAssignableTo(targetType, sourceType);
|
|
157
291
|
}
|
|
158
|
-
function
|
|
159
|
-
|
|
160
|
-
|
|
292
|
+
function mergeTypeNames(typeWithNames, operator) {
|
|
293
|
+
if (typeWithNames.length === 1) {
|
|
294
|
+
return typeWithNames[0].typeName;
|
|
295
|
+
}
|
|
296
|
+
const wrapType = (typeWithName) => {
|
|
297
|
+
if (operator === '|' && typeWithName.type.isIntersection()) {
|
|
298
|
+
return `(${typeWithName.typeName})`;
|
|
299
|
+
}
|
|
300
|
+
if (operator === '&' && typeWithName.type.isUnion()) {
|
|
301
|
+
return `(${typeWithName.typeName})`;
|
|
302
|
+
}
|
|
303
|
+
return typeWithName.typeName;
|
|
304
|
+
};
|
|
305
|
+
return typeWithNames.map(wrapType).join(` ${operator} `);
|
|
161
306
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
tsutils.isFalseLiteralType(type.types[0]) &&
|
|
169
|
-
tsutils.isTrueLiteralType(type.types[1])
|
|
170
|
-
? [type]
|
|
171
|
-
: tsutils.unionConstituents(type);
|
|
307
|
+
function getGroupTypeRelationsByNonRedundantType(typeRedundancyRelations) {
|
|
308
|
+
const groups = new Map();
|
|
309
|
+
for (const typeRedundancyRelation of typeRedundancyRelations) {
|
|
310
|
+
addToMapGroup(groups, typeRedundancyRelation.nonRedundantTypeWithName.type, typeRedundancyRelation);
|
|
311
|
+
}
|
|
312
|
+
return groups;
|
|
172
313
|
}
|
|
173
314
|
exports.default = (0, util_1.createRule)({
|
|
174
315
|
name: 'no-redundant-type-constituents',
|
|
@@ -181,61 +322,68 @@ exports.default = (0, util_1.createRule)({
|
|
|
181
322
|
},
|
|
182
323
|
messages: {
|
|
183
324
|
errorTypeOverrides: `'{{typeName}}' is an 'error' type that acts as 'any' and overrides all other types in this {{container}} type.`,
|
|
184
|
-
literalOverridden: `{{literal}} is overridden by {{primitive}} in this union type.`,
|
|
185
325
|
overridden: `'{{typeName}}' is overridden by other types in this {{container}} type.`,
|
|
186
326
|
overrides: `'{{typeName}}' overrides all other types in this {{container}} type.`,
|
|
187
|
-
|
|
327
|
+
typeOverridden: `{{redundantType}} is overridden by {{nonRedundantType}} in this {{container}} type.`,
|
|
188
328
|
},
|
|
189
329
|
schema: [],
|
|
190
330
|
},
|
|
191
331
|
defaultOptions: [],
|
|
192
332
|
create(context) {
|
|
193
333
|
const services = (0, util_1.getParserServices)(context);
|
|
194
|
-
const
|
|
195
|
-
function
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
334
|
+
const checker = services.program.getTypeChecker();
|
|
335
|
+
function reportRedundantTypes(redundantTypes, container) {
|
|
336
|
+
for (const [typeNode, typeRelations] of redundantTypes) {
|
|
337
|
+
const groupTypeRelationsByNonRedundantType = getGroupTypeRelationsByNonRedundantType(typeRelations);
|
|
338
|
+
for (const [nonRedundantType, typeRelationAndNames,] of groupTypeRelationsByNonRedundantType) {
|
|
339
|
+
const nonRedundantTypeName = checker.typeToString(nonRedundantType);
|
|
340
|
+
const mergedRedundantTypeName = mergeTypeNames(typeRelationAndNames.map(({ redundantTypeWithName }) => redundantTypeWithName), container === 'union' ? '|' : '&');
|
|
341
|
+
context.report({
|
|
342
|
+
node: typeNode,
|
|
343
|
+
messageId: 'typeOverridden',
|
|
344
|
+
data: {
|
|
345
|
+
container,
|
|
346
|
+
nonRedundantType: nonRedundantTypeName,
|
|
347
|
+
redundantType: mergedRedundantTypeName,
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
}
|
|
204
351
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
typeFlags: primitiveTypeFlagTypes[typeof typeNode.literal
|
|
210
|
-
.value],
|
|
211
|
-
typeName: describeLiteralTypeNode(typeNode),
|
|
212
|
-
},
|
|
213
|
-
];
|
|
352
|
+
}
|
|
353
|
+
function getUnionTypePart(typeNode, checker) {
|
|
354
|
+
if (ts.isParenthesizedTypeNode(typeNode)) {
|
|
355
|
+
return getUnionTypePart(typeNode.type, checker);
|
|
214
356
|
}
|
|
215
|
-
if (typeNode
|
|
216
|
-
return typeNode.types.flatMap(
|
|
357
|
+
if (ts.isUnionTypeNode(typeNode)) {
|
|
358
|
+
return typeNode.types.flatMap(typeNode => getUnionTypePart(typeNode, checker));
|
|
217
359
|
}
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
360
|
+
const type = checker.getTypeAtLocation(typeNode);
|
|
361
|
+
return [
|
|
362
|
+
{
|
|
363
|
+
type,
|
|
364
|
+
typeName: checker.typeToString(type),
|
|
365
|
+
},
|
|
366
|
+
];
|
|
224
367
|
}
|
|
225
|
-
function
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
368
|
+
function getIntersectionTypePart(typeNode, checker) {
|
|
369
|
+
if (ts.isParenthesizedTypeNode(typeNode)) {
|
|
370
|
+
return getIntersectionTypePart(typeNode.type, checker);
|
|
371
|
+
}
|
|
372
|
+
if (ts.isIntersectionTypeNode(typeNode)) {
|
|
373
|
+
return typeNode.types.flatMap(typeNode => getIntersectionTypePart(typeNode, checker));
|
|
229
374
|
}
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
375
|
+
const type = checker.getTypeAtLocation(typeNode);
|
|
376
|
+
return [
|
|
377
|
+
{
|
|
378
|
+
type,
|
|
379
|
+
typeName: checker.typeToString(type),
|
|
380
|
+
},
|
|
381
|
+
];
|
|
233
382
|
}
|
|
234
383
|
return {
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
-
const seenUnionTypes = new Map();
|
|
384
|
+
TSIntersectionType(node) {
|
|
385
|
+
const seenTypes = new Set();
|
|
386
|
+
const redundantTypes = new Map();
|
|
239
387
|
function checkIntersectionBottomAndTopTypes({ typeFlags, typeName }, typeNode) {
|
|
240
388
|
for (const [messageId, checkFlag] of [
|
|
241
389
|
['overrides', ts.TypeFlags.Any],
|
|
@@ -259,87 +407,70 @@ exports.default = (0, util_1.createRule)({
|
|
|
259
407
|
return false;
|
|
260
408
|
}
|
|
261
409
|
for (const typeNode of node.types) {
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
410
|
+
const tsTypeNode = services.esTreeNodeToTSNodeMap.get(typeNode);
|
|
411
|
+
const typeParts = getIntersectionTypePart(tsTypeNode, checker);
|
|
412
|
+
for (const typePart of typeParts) {
|
|
413
|
+
if (typePart.type.flags & ts.TypeFlags.Never ||
|
|
414
|
+
typePart.type.flags & ts.TypeFlags.Any ||
|
|
415
|
+
typePart.type.flags & ts.TypeFlags.Unknown) {
|
|
416
|
+
checkIntersectionBottomAndTopTypes({
|
|
417
|
+
typeFlags: typePart.type.flags,
|
|
418
|
+
typeName: typePart.typeName,
|
|
419
|
+
}, typeNode);
|
|
265
420
|
continue;
|
|
266
421
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
422
|
+
const { type: targetType, typeName: targetTypeName } = typePart;
|
|
423
|
+
for (const seenType of seenTypes) {
|
|
424
|
+
const { type: sourceType, parentTypeNode, typeName: sourceTypeName, } = seenType;
|
|
425
|
+
const targetTypeIsRedundant = isTargetTypeRedundantInIntersection(sourceType, targetType, checker);
|
|
426
|
+
const sourceTypeIsRedundant = isTargetTypeRedundantInIntersection(targetType, sourceType, checker);
|
|
427
|
+
if (targetTypeIsRedundant &&
|
|
428
|
+
targetTypeIsRedundant === sourceTypeIsRedundant) {
|
|
429
|
+
continue;
|
|
271
430
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* @example
|
|
286
|
-
* ```ts
|
|
287
|
-
* type F = "a"|2|"b";
|
|
288
|
-
* type I = F & string;
|
|
289
|
-
* ```
|
|
290
|
-
* This function checks if all the union members of `F` are assignable to the other member of `I`. If every member is assignable, then its reported else not.
|
|
291
|
-
*/
|
|
292
|
-
const checkIfUnionsAreAssignable = () => {
|
|
293
|
-
for (const [typeRef, typeValues] of seenUnionTypes) {
|
|
294
|
-
let primitive = undefined;
|
|
295
|
-
for (const { typeFlags } of typeValues) {
|
|
296
|
-
if (seenPrimitiveTypes.has(literalToPrimitiveTypeFlags[typeFlags])) {
|
|
297
|
-
primitive =
|
|
298
|
-
literalToPrimitiveTypeFlags[typeFlags];
|
|
431
|
+
if (sourceTypeIsRedundant) {
|
|
432
|
+
addToMapGroup(redundantTypes, parentTypeNode, {
|
|
433
|
+
nonRedundantTypeWithName: {
|
|
434
|
+
type: targetType,
|
|
435
|
+
typeName: targetTypeName,
|
|
436
|
+
},
|
|
437
|
+
redundantTypeWithName: {
|
|
438
|
+
type: sourceType,
|
|
439
|
+
typeName: sourceTypeName,
|
|
440
|
+
},
|
|
441
|
+
});
|
|
299
442
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
443
|
+
if (targetTypeIsRedundant) {
|
|
444
|
+
addToMapGroup(redundantTypes, typeNode, {
|
|
445
|
+
nonRedundantTypeWithName: {
|
|
446
|
+
type: sourceType,
|
|
447
|
+
typeName: sourceTypeName,
|
|
448
|
+
},
|
|
449
|
+
redundantTypeWithName: {
|
|
450
|
+
type: targetType,
|
|
451
|
+
typeName: targetTypeName,
|
|
452
|
+
},
|
|
453
|
+
});
|
|
303
454
|
}
|
|
304
455
|
}
|
|
305
|
-
if (Number.isInteger(primitive)) {
|
|
306
|
-
context.report({
|
|
307
|
-
node: typeRef,
|
|
308
|
-
messageId: 'primitiveOverridden',
|
|
309
|
-
data: {
|
|
310
|
-
literal: typeValues.map(name => name.typeName).join(' | '),
|
|
311
|
-
primitive: primitiveTypeFlagNames[primitive],
|
|
312
|
-
},
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
456
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
// For each primitive type of all the seen primitive types,
|
|
322
|
-
// if there was a literal type seen that overrides it,
|
|
323
|
-
// report each of the primitive type's type nodes
|
|
324
|
-
for (const [primitiveTypeFlag, typeNodes] of seenPrimitiveTypes) {
|
|
325
|
-
const matchedLiteralTypes = seenLiteralTypes.get(primitiveTypeFlag);
|
|
326
|
-
if (matchedLiteralTypes) {
|
|
327
|
-
for (const typeNode of typeNodes) {
|
|
328
|
-
context.report({
|
|
329
|
-
node: typeNode,
|
|
330
|
-
messageId: 'primitiveOverridden',
|
|
331
|
-
data: {
|
|
332
|
-
literal: matchedLiteralTypes.join(' | '),
|
|
333
|
-
primitive: primitiveTypeFlagNames[primitiveTypeFlag],
|
|
334
|
-
},
|
|
335
|
-
});
|
|
457
|
+
for (const typePart of typeParts) {
|
|
458
|
+
if (typePart.type.flags === ts.TypeFlags.Any ||
|
|
459
|
+
typePart.type.flags === ts.TypeFlags.Unknown ||
|
|
460
|
+
typePart.type.flags === ts.TypeFlags.Never) {
|
|
461
|
+
continue;
|
|
336
462
|
}
|
|
463
|
+
seenTypes.add({
|
|
464
|
+
...typePart,
|
|
465
|
+
parentTypeNode: typeNode,
|
|
466
|
+
});
|
|
337
467
|
}
|
|
338
468
|
}
|
|
469
|
+
reportRedundantTypes(redundantTypes, 'intersection');
|
|
339
470
|
},
|
|
340
|
-
|
|
341
|
-
const
|
|
342
|
-
const
|
|
471
|
+
TSUnionType(node) {
|
|
472
|
+
const seenTypes = new Set();
|
|
473
|
+
const redundantTypes = new Map();
|
|
343
474
|
function checkUnionBottomAndTopTypes({ typeFlags, typeName }, typeNode) {
|
|
344
475
|
for (const checkFlag of [
|
|
345
476
|
ts.TypeFlags.Any,
|
|
@@ -360,7 +491,7 @@ exports.default = (0, util_1.createRule)({
|
|
|
360
491
|
}
|
|
361
492
|
}
|
|
362
493
|
if (typeFlags === ts.TypeFlags.Never &&
|
|
363
|
-
!
|
|
494
|
+
!isUnionNodeInsideReturnType(node)) {
|
|
364
495
|
context.report({
|
|
365
496
|
node: typeNode,
|
|
366
497
|
messageId: 'overridden',
|
|
@@ -374,57 +505,66 @@ exports.default = (0, util_1.createRule)({
|
|
|
374
505
|
return false;
|
|
375
506
|
}
|
|
376
507
|
for (const typeNode of node.types) {
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
508
|
+
const tsTypeNode = services.esTreeNodeToTSNodeMap.get(typeNode);
|
|
509
|
+
const typeParts = getUnionTypePart(tsTypeNode, checker);
|
|
510
|
+
for (const typePart of typeParts) {
|
|
511
|
+
if (typePart.type.flags & ts.TypeFlags.Never ||
|
|
512
|
+
typePart.type.flags & ts.TypeFlags.Any ||
|
|
513
|
+
typePart.type.flags & ts.TypeFlags.Unknown) {
|
|
514
|
+
checkUnionBottomAndTopTypes({
|
|
515
|
+
typeFlags: typePart.type.flags,
|
|
516
|
+
typeName: typePart.typeName,
|
|
517
|
+
}, typeNode);
|
|
380
518
|
continue;
|
|
381
519
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
520
|
+
const { type: targetType, typeName: targetTypeName } = typePart;
|
|
521
|
+
for (const seenType of seenTypes) {
|
|
522
|
+
const { type: sourceType, parentTypeNode, typeName: sourceTypeName, } = seenType;
|
|
523
|
+
const targetTypeIsRedundant = isTargetTypeRedundantInUnion(sourceType, targetType, checker);
|
|
524
|
+
const sourceTypeIsRedundant = isTargetTypeRedundantInUnion(targetType, sourceType, checker);
|
|
525
|
+
if (targetTypeIsRedundant &&
|
|
526
|
+
targetTypeIsRedundant === sourceTypeIsRedundant) {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
if (sourceTypeIsRedundant) {
|
|
530
|
+
addToMapGroup(redundantTypes, parentTypeNode, {
|
|
531
|
+
nonRedundantTypeWithName: {
|
|
532
|
+
type: targetType,
|
|
533
|
+
typeName: targetTypeName,
|
|
534
|
+
},
|
|
535
|
+
redundantTypeWithName: {
|
|
536
|
+
type: sourceType,
|
|
537
|
+
typeName: sourceTypeName,
|
|
538
|
+
},
|
|
387
539
|
});
|
|
388
|
-
break;
|
|
389
540
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
541
|
+
if (targetTypeIsRedundant) {
|
|
542
|
+
addToMapGroup(redundantTypes, typeNode, {
|
|
543
|
+
nonRedundantTypeWithName: {
|
|
544
|
+
type: sourceType,
|
|
545
|
+
typeName: sourceTypeName,
|
|
546
|
+
},
|
|
547
|
+
redundantTypeWithName: {
|
|
548
|
+
type: targetType,
|
|
549
|
+
typeName: targetTypeName,
|
|
550
|
+
},
|
|
551
|
+
});
|
|
394
552
|
}
|
|
395
553
|
}
|
|
396
554
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
for (const [primitiveTypeFlag, typeNodesWithText] of seenLiteralTypes) {
|
|
403
|
-
if (seenPrimitiveTypes.has(primitiveTypeFlag)) {
|
|
404
|
-
for (const { literalValue, typeNode } of typeNodesWithText) {
|
|
405
|
-
addToMapGroup(overriddenTypeNodes, typeNode, {
|
|
406
|
-
literalValue,
|
|
407
|
-
primitiveTypeFlag,
|
|
408
|
-
});
|
|
555
|
+
for (const typePart of typeParts) {
|
|
556
|
+
if (typePart.type.flags === ts.TypeFlags.Any ||
|
|
557
|
+
typePart.type.flags === ts.TypeFlags.Unknown ||
|
|
558
|
+
typePart.type.flags === ts.TypeFlags.Never) {
|
|
559
|
+
continue;
|
|
409
560
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
// group those literals by their primitive type,
|
|
414
|
-
// then report each primitive type with all its literals
|
|
415
|
-
for (const [typeNode, typeFlagsWithText] of overriddenTypeNodes) {
|
|
416
|
-
const grouped = (0, util_1.arrayGroupByToMap)(typeFlagsWithText, pair => pair.primitiveTypeFlag);
|
|
417
|
-
for (const [primitiveTypeFlag, pairs] of grouped) {
|
|
418
|
-
context.report({
|
|
419
|
-
node: typeNode,
|
|
420
|
-
messageId: 'literalOverridden',
|
|
421
|
-
data: {
|
|
422
|
-
literal: pairs.map(pair => pair.literalValue).join(' | '),
|
|
423
|
-
primitive: primitiveTypeFlagNames[primitiveTypeFlag],
|
|
424
|
-
},
|
|
561
|
+
seenTypes.add({
|
|
562
|
+
...typePart,
|
|
563
|
+
parentTypeNode: typeNode,
|
|
425
564
|
});
|
|
426
565
|
}
|
|
427
566
|
}
|
|
567
|
+
reportRedundantTypes(redundantTypes, 'union');
|
|
428
568
|
},
|
|
429
569
|
};
|
|
430
570
|
},
|
|
@@ -64,7 +64,6 @@ exports.default = (0, util_1.createRule)({
|
|
|
64
64
|
((node.parameter.type === utils_1.AST_NODE_TYPES.Identifier && // constructor (public foo) {}
|
|
65
65
|
node.parameter.name === name) ||
|
|
66
66
|
(node.parameter.type === utils_1.AST_NODE_TYPES.AssignmentPattern && // constructor (public foo = 1) {}
|
|
67
|
-
node.parameter.left.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
68
67
|
node.parameter.left.name === name)));
|
|
69
68
|
}
|
|
70
69
|
function getIdentifier(node) {
|
|
@@ -74,15 +74,9 @@ exports.default = (0, util_1.createRule)({
|
|
|
74
74
|
TSParameterProperty(node) {
|
|
75
75
|
const modifiers = getModifiers(node);
|
|
76
76
|
if (!allow.includes(modifiers)) {
|
|
77
|
-
// HAS to be an identifier or assignment or TSC will throw
|
|
78
|
-
if (node.parameter.type !== utils_1.AST_NODE_TYPES.Identifier &&
|
|
79
|
-
node.parameter.type !== utils_1.AST_NODE_TYPES.AssignmentPattern) {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
77
|
const name = node.parameter.type === utils_1.AST_NODE_TYPES.Identifier
|
|
83
78
|
? node.parameter.name
|
|
84
|
-
:
|
|
85
|
-
node.parameter.left.name;
|
|
79
|
+
: node.parameter.left.name;
|
|
86
80
|
context.report({
|
|
87
81
|
node,
|
|
88
82
|
messageId: 'preferClassProperty',
|
|
@@ -5,7 +5,7 @@ type OptionTester = (type: Type, checker: TypeChecker, recursivelyCheckType: (ty
|
|
|
5
5
|
declare const optionTesters: {
|
|
6
6
|
type: "Array" | "RegExp" | "Boolean" | "Number" | "Any" | "Nullish" | "Never";
|
|
7
7
|
option: "allowAny" | "allowBoolean" | "allowNullish" | "allowRegExp" | "allowNever" | "allowNumber" | "allowArray";
|
|
8
|
-
tester: typeof isTypeAnyType |
|
|
8
|
+
tester: typeof isTypeAnyType | OptionTester | ((type: Type, checker: TypeChecker, recursivelyCheckType: (type: Type) => boolean) => boolean) | ((type: Type, checker: TypeChecker) => boolean) | typeof isTypeNeverType;
|
|
9
9
|
}[];
|
|
10
10
|
export type Options = [
|
|
11
11
|
{
|
|
@@ -45,20 +45,10 @@ function extractNonComputedName(nonComputedName) {
|
|
|
45
45
|
*/
|
|
46
46
|
function extractNameForMember(node) {
|
|
47
47
|
if (node.type === utils_1.AST_NODE_TYPES.TSParameterProperty) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// Nonsensical properties -- see https://github.com/typescript-eslint/typescript-eslint/issues/11708
|
|
53
|
-
return null;
|
|
54
|
-
case utils_1.AST_NODE_TYPES.AssignmentPattern:
|
|
55
|
-
if (node.parameter.left.type !== utils_1.AST_NODE_TYPES.Identifier) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
return extractNonComputedName(node.parameter.left);
|
|
59
|
-
case utils_1.AST_NODE_TYPES.Identifier:
|
|
60
|
-
return extractNonComputedName(node.parameter);
|
|
61
|
-
}
|
|
48
|
+
const identifier = node.parameter.type === utils_1.AST_NODE_TYPES.Identifier
|
|
49
|
+
? node.parameter
|
|
50
|
+
: node.parameter.left;
|
|
51
|
+
return extractNonComputedName(identifier);
|
|
62
52
|
}
|
|
63
53
|
if (node.computed) {
|
|
64
54
|
return extractComputedName(node.key);
|
|
@@ -81,20 +81,16 @@ class UnusedVarsVisitor extends scope_manager_1.Visitor {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
TSParameterProperty(node) {
|
|
84
|
-
let identifier
|
|
84
|
+
let identifier;
|
|
85
85
|
switch (node.parameter.type) {
|
|
86
86
|
case utils_1.AST_NODE_TYPES.AssignmentPattern:
|
|
87
|
-
|
|
88
|
-
identifier = node.parameter.left;
|
|
89
|
-
}
|
|
87
|
+
identifier = node.parameter.left;
|
|
90
88
|
break;
|
|
91
89
|
case utils_1.AST_NODE_TYPES.Identifier:
|
|
92
90
|
identifier = node.parameter;
|
|
93
91
|
break;
|
|
94
92
|
}
|
|
95
|
-
|
|
96
|
-
this.markVariableAsUsed(identifier);
|
|
97
|
-
}
|
|
93
|
+
this.markVariableAsUsed(identifier);
|
|
98
94
|
}
|
|
99
95
|
collectUnusedVariables(scope, variables = {
|
|
100
96
|
unusedVariables: new Set(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typescript-eslint/eslint-plugin",
|
|
3
|
-
"version": "8.47.1-alpha.
|
|
3
|
+
"version": "8.47.1-alpha.11",
|
|
4
4
|
"description": "TypeScript plugin for ESLint",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
61
|
"@eslint-community/regexpp": "^4.10.0",
|
|
62
|
-
"@typescript-eslint/scope-manager": "8.47.1-alpha.
|
|
63
|
-
"@typescript-eslint/type-utils": "8.47.1-alpha.
|
|
64
|
-
"@typescript-eslint/utils": "8.47.1-alpha.
|
|
65
|
-
"@typescript-eslint/visitor-keys": "8.47.1-alpha.
|
|
62
|
+
"@typescript-eslint/scope-manager": "8.47.1-alpha.11",
|
|
63
|
+
"@typescript-eslint/type-utils": "8.47.1-alpha.11",
|
|
64
|
+
"@typescript-eslint/utils": "8.47.1-alpha.11",
|
|
65
|
+
"@typescript-eslint/visitor-keys": "8.47.1-alpha.11",
|
|
66
66
|
"graphemer": "^1.4.0",
|
|
67
67
|
"ignore": "^7.0.0",
|
|
68
68
|
"natural-compare": "^1.4.0",
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/mdast": "^4.0.3",
|
|
73
73
|
"@types/natural-compare": "*",
|
|
74
|
-
"@typescript-eslint/rule-schema-to-typescript-types": "8.47.1-alpha.
|
|
75
|
-
"@typescript-eslint/rule-tester": "8.47.1-alpha.
|
|
74
|
+
"@typescript-eslint/rule-schema-to-typescript-types": "8.47.1-alpha.11",
|
|
75
|
+
"@typescript-eslint/rule-tester": "8.47.1-alpha.11",
|
|
76
76
|
"@vitest/coverage-v8": "^3.1.3",
|
|
77
77
|
"ajv": "^6.12.6",
|
|
78
78
|
"cross-fetch": "*",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"vitest": "^3.1.3"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
95
|
-
"@typescript-eslint/parser": "^8.47.1-alpha.
|
|
95
|
+
"@typescript-eslint/parser": "^8.47.1-alpha.11",
|
|
96
96
|
"eslint": "^8.57.0 || ^9.0.0",
|
|
97
97
|
"typescript": ">=4.8.4 <6.0.0"
|
|
98
98
|
},
|