@taiga-ui/eslint-plugin-experience-next 0.458.0 → 0.460.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -0
- package/index.d.ts +4 -1
- package/index.esm.js +151 -21
- package/package.json +6 -6
- package/rules/no-project-as-in-ng-template.d.ts +3 -0
- package/rules/no-redundant-type-annotation.d.ts +6 -1
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ export default [
|
|
|
49
49
|
| no-href-with-router-link | Do not use href and routerLink attributes together on the same element | | 🔧 | |
|
|
50
50
|
| no-implicit-public | Require explicit `public` modifier for class members and parameter properties | ✅ | 🔧 | |
|
|
51
51
|
| no-playwright-empty-fill | Enforce `clear()` over `fill('')` in Playwright tests | ✅ | 🔧 | |
|
|
52
|
+
| no-project-as-in-ng-template | `ngProjectAs` has no effect inside `<ng-template>` or dynamic outlets | | | |
|
|
52
53
|
| no-redundant-type-annotation | Disallow redundant type annotations when the type is already inferred from the initializer | ✅ | 🔧 | |
|
|
53
54
|
| no-string-literal-concat | Disallow string literal concatenation; merge adjacent literals into one | ✅ | 🔧 | |
|
|
54
55
|
| object-single-line | Enforce single-line formatting for single-property objects when it fits `printWidth` | ✅ | 🔧 | |
|
|
@@ -285,6 +286,36 @@ await page.getByLabel('Name').clear();
|
|
|
285
286
|
|
|
286
287
|
---
|
|
287
288
|
|
|
289
|
+
## no-project-as-in-ng-template
|
|
290
|
+
|
|
291
|
+
`ngProjectAs` has no effect when the element is inside an `<ng-template>`, `*ngTemplateOutlet`, `*ngComponentOutlet`, or
|
|
292
|
+
`*polymorpheusOutlet`. Content instantiated through these dynamic outlets does not participate in Angular's static
|
|
293
|
+
content projection, so the attribute is silently ignored at runtime.
|
|
294
|
+
|
|
295
|
+
```html
|
|
296
|
+
<!-- ❌ error — inside <ng-template> -->
|
|
297
|
+
<ng-template #tpl>
|
|
298
|
+
<div ngProjectAs="[someSlot]">content</div>
|
|
299
|
+
</ng-template>
|
|
300
|
+
|
|
301
|
+
<!-- ❌ error — on the outlet host itself -->
|
|
302
|
+
<ng-container
|
|
303
|
+
*ngTemplateOutlet="tpl"
|
|
304
|
+
ngProjectAs="[someSlot]"
|
|
305
|
+
></ng-container>
|
|
306
|
+
|
|
307
|
+
<!-- ❌ error — polymorpheusOutlet -->
|
|
308
|
+
<ng-container
|
|
309
|
+
*polymorpheusOutlet="content"
|
|
310
|
+
ngProjectAs="someSlot"
|
|
311
|
+
></ng-container>
|
|
312
|
+
|
|
313
|
+
<!-- ✅ ok — static content projection -->
|
|
314
|
+
<div ngProjectAs="[someSlot]">content</div>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
288
319
|
## no-string-literal-concat
|
|
289
320
|
|
|
290
321
|
Disallows concatenating string literals with `+`. Adjacent string literals are always mergeable into one — splitting
|
|
@@ -536,6 +567,32 @@ x: Animal = new Dog();
|
|
|
536
567
|
x: MyService | null = inject(MyService);
|
|
537
568
|
```
|
|
538
569
|
|
|
570
|
+
The rule does **not** report when the annotation provides contextual typing that narrows an array literal to a tuple.
|
|
571
|
+
Without the annotation TypeScript would infer `number[]` instead of the required tuple type, widening the type and
|
|
572
|
+
breaking compilation:
|
|
573
|
+
|
|
574
|
+
```ts
|
|
575
|
+
type SelectionRange = readonly [from: number, to: number];
|
|
576
|
+
interface ElementState {
|
|
577
|
+
readonly value: string;
|
|
578
|
+
readonly selection: SelectionRange;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// ✅ ok — [0, 0] is inferred as SelectionRange only because of the annotation;
|
|
582
|
+
// removing it would widen the type to ElementState | {value: string; selection: number[]}
|
|
583
|
+
const state: ElementState = flag ? {value: '', selection: [0, 0]} : existingState;
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
```json
|
|
587
|
+
{
|
|
588
|
+
"@taiga-ui/experience-next/no-redundant-type-annotation": ["error", {"ignoreTupleContextualTyping": true}]
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
| Option | Type | Default | Description |
|
|
593
|
+
| ----------------------------- | --------- | ------- | ------------------------------------------------------------------------------------------------------ |
|
|
594
|
+
| `ignoreTupleContextualTyping` | `boolean` | `true` | Preserve annotations when they provide contextual typing that narrows an array literal to a tuple type |
|
|
595
|
+
|
|
539
596
|
---
|
|
540
597
|
|
|
541
598
|
## strict-tui-doc-example
|
package/index.d.ts
CHANGED
|
@@ -40,7 +40,10 @@ declare const plugin: {
|
|
|
40
40
|
'no-playwright-empty-fill': import("@typescript-eslint/utils/ts-eslint").RuleModule<"useClear", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
41
41
|
name: string;
|
|
42
42
|
};
|
|
43
|
-
'no-
|
|
43
|
+
'no-project-as-in-ng-template': import("eslint").Rule.RuleModule;
|
|
44
|
+
'no-redundant-type-annotation': import("@typescript-eslint/utils/ts-eslint").RuleModule<"redundantTypeAnnotation", [({
|
|
45
|
+
ignoreTupleContextualTyping?: boolean;
|
|
46
|
+
} | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
44
47
|
name: string;
|
|
45
48
|
};
|
|
46
49
|
'no-string-literal-concat': import("@typescript-eslint/utils/ts-eslint").RuleModule<"flattenTemplate" | "mergeLiterals" | "useTemplate", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
package/index.esm.js
CHANGED
|
@@ -32,6 +32,7 @@ import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
|
32
32
|
import ts, { isCallExpression } from 'typescript';
|
|
33
33
|
import { AST_NODE_TYPES as AST_NODE_TYPES$1 } from '@typescript-eslint/types';
|
|
34
34
|
import path from 'node:path';
|
|
35
|
+
import { TmplAstTemplate } from '@angular-eslint/bundled-angular-compiler';
|
|
35
36
|
|
|
36
37
|
var htmlEslint = defineConfig([
|
|
37
38
|
{
|
|
@@ -630,7 +631,7 @@ var recommended = defineConfig([
|
|
|
630
631
|
'max-depth': 'error',
|
|
631
632
|
'max-nested-callbacks': ['error', 4],
|
|
632
633
|
'max-params': ['error', 5],
|
|
633
|
-
'no-bitwise': '
|
|
634
|
+
'no-bitwise': 'off',
|
|
634
635
|
'no-case-declarations': 'error',
|
|
635
636
|
'no-console': ['error', { allow: ['info', 'assert', 'warn', 'error'] }],
|
|
636
637
|
'no-constant-condition': 'error',
|
|
@@ -989,6 +990,7 @@ var recommended = defineConfig([
|
|
|
989
990
|
'@angular-eslint/template/prefer-control-flow': angularVersion >= modernAngularRules.preferControlFlow ? 'error' : 'off',
|
|
990
991
|
'@angular-eslint/template/prefer-self-closing-tags': 'error',
|
|
991
992
|
'@angular-eslint/template/prefer-template-literal': angularVersion >= modernAngularRules.templateLiteral ? 'error' : 'off',
|
|
993
|
+
'@taiga-ui/experience-next/no-project-as-in-ng-template': 'error',
|
|
992
994
|
},
|
|
993
995
|
},
|
|
994
996
|
{
|
|
@@ -1238,7 +1240,7 @@ function readJSON(path) {
|
|
|
1238
1240
|
}
|
|
1239
1241
|
}
|
|
1240
1242
|
|
|
1241
|
-
const config$
|
|
1243
|
+
const config$3 = {
|
|
1242
1244
|
create(context) {
|
|
1243
1245
|
const classesInFile = new Map();
|
|
1244
1246
|
return {
|
|
@@ -1292,7 +1294,6 @@ const config$2 = {
|
|
|
1292
1294
|
},
|
|
1293
1295
|
};
|
|
1294
1296
|
|
|
1295
|
-
/* eslint-disable no-bitwise */
|
|
1296
1297
|
function getFieldTypes(type, checker) {
|
|
1297
1298
|
const typeNames = [];
|
|
1298
1299
|
if (type.isUnionOrIntersection()) {
|
|
@@ -1398,7 +1399,7 @@ var classPropertyNaming = createRule$e({
|
|
|
1398
1399
|
name: 'class-property-naming',
|
|
1399
1400
|
});
|
|
1400
1401
|
|
|
1401
|
-
const config$
|
|
1402
|
+
const config$2 = {
|
|
1402
1403
|
create(context) {
|
|
1403
1404
|
const order = context.options[0] || {};
|
|
1404
1405
|
return {
|
|
@@ -1501,7 +1502,7 @@ function isExternalPureTuple(typeChecker, type) {
|
|
|
1501
1502
|
}
|
|
1502
1503
|
|
|
1503
1504
|
const createRule$d = ESLintUtils.RuleCreator((name) => name);
|
|
1504
|
-
const MESSAGE_ID$
|
|
1505
|
+
const MESSAGE_ID$6 = 'spreadArrays';
|
|
1505
1506
|
var flatExports = createRule$d({
|
|
1506
1507
|
create(context) {
|
|
1507
1508
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
@@ -1567,7 +1568,7 @@ var flatExports = createRule$d({
|
|
|
1567
1568
|
fix(fixer) {
|
|
1568
1569
|
return fixer.replaceText(elementNode, `...${meta.name}`);
|
|
1569
1570
|
},
|
|
1570
|
-
messageId: MESSAGE_ID$
|
|
1571
|
+
messageId: MESSAGE_ID$6,
|
|
1571
1572
|
node: elementNode,
|
|
1572
1573
|
});
|
|
1573
1574
|
}
|
|
@@ -1618,7 +1619,7 @@ var flatExports = createRule$d({
|
|
|
1618
1619
|
},
|
|
1619
1620
|
fixable: 'code',
|
|
1620
1621
|
messages: {
|
|
1621
|
-
[MESSAGE_ID$
|
|
1622
|
+
[MESSAGE_ID$6]: 'Spread "{{ name }}" to avoid nested arrays in exported entities.',
|
|
1622
1623
|
},
|
|
1623
1624
|
schema: [],
|
|
1624
1625
|
type: 'suggestion',
|
|
@@ -1626,7 +1627,7 @@ var flatExports = createRule$d({
|
|
|
1626
1627
|
name: 'flat-exports',
|
|
1627
1628
|
});
|
|
1628
1629
|
|
|
1629
|
-
const MESSAGE_ID$
|
|
1630
|
+
const MESSAGE_ID$5 = 'invalid-injection-token-description';
|
|
1630
1631
|
const ERROR_MESSAGE$3 = "InjectionToken's description should contain token's name";
|
|
1631
1632
|
const createRule$c = ESLintUtils.RuleCreator((name) => name);
|
|
1632
1633
|
const rule$9 = createRule$c({
|
|
@@ -1660,7 +1661,7 @@ const rule$9 = createRule$c({
|
|
|
1660
1661
|
const [start, end] = description.range;
|
|
1661
1662
|
return fixer.insertTextBeforeRange([start + 1, end], `[${name}]: `);
|
|
1662
1663
|
},
|
|
1663
|
-
messageId: MESSAGE_ID$
|
|
1664
|
+
messageId: MESSAGE_ID$5,
|
|
1664
1665
|
node: description,
|
|
1665
1666
|
});
|
|
1666
1667
|
}
|
|
@@ -1670,14 +1671,14 @@ const rule$9 = createRule$c({
|
|
|
1670
1671
|
meta: {
|
|
1671
1672
|
docs: { description: ERROR_MESSAGE$3 },
|
|
1672
1673
|
fixable: 'code',
|
|
1673
|
-
messages: { [MESSAGE_ID$
|
|
1674
|
+
messages: { [MESSAGE_ID$5]: ERROR_MESSAGE$3 },
|
|
1674
1675
|
schema: [],
|
|
1675
1676
|
type: 'problem',
|
|
1676
1677
|
},
|
|
1677
1678
|
name: 'injection-token-description',
|
|
1678
1679
|
});
|
|
1679
1680
|
|
|
1680
|
-
const MESSAGE_ID$
|
|
1681
|
+
const MESSAGE_ID$4 = 'no-deep-imports';
|
|
1681
1682
|
const ERROR_MESSAGE$2 = 'Deep imports of Taiga UI packages are prohibited';
|
|
1682
1683
|
const CODE_EXTENSIONS = new Set([
|
|
1683
1684
|
'.cjs',
|
|
@@ -1739,7 +1740,7 @@ const rule$8 = createRule$b({
|
|
|
1739
1740
|
const [start, end] = node.source.range;
|
|
1740
1741
|
return fixer.replaceTextRange([start + 1, end - 1], importSource.replaceAll(new RegExp(deepImport, 'g'), ''));
|
|
1741
1742
|
},
|
|
1742
|
-
messageId: MESSAGE_ID$
|
|
1743
|
+
messageId: MESSAGE_ID$4,
|
|
1743
1744
|
node: node.source,
|
|
1744
1745
|
});
|
|
1745
1746
|
},
|
|
@@ -1749,7 +1750,7 @@ const rule$8 = createRule$b({
|
|
|
1749
1750
|
defaultOptions: [DEFAULT_OPTIONS],
|
|
1750
1751
|
docs: { description: ERROR_MESSAGE$2 },
|
|
1751
1752
|
fixable: 'code',
|
|
1752
|
-
messages: { [MESSAGE_ID$
|
|
1753
|
+
messages: { [MESSAGE_ID$4]: ERROR_MESSAGE$2 },
|
|
1753
1754
|
schema: [
|
|
1754
1755
|
{
|
|
1755
1756
|
additionalProperties: false,
|
|
@@ -1985,9 +1986,9 @@ function stripKnownExtensions(filePathOrSpecifier) {
|
|
|
1985
1986
|
return filePathOrSpecifier.replace(/\.(?:d\.ts|ts|tsx|js|jsx|mjs|cjs)$/, '');
|
|
1986
1987
|
}
|
|
1987
1988
|
|
|
1988
|
-
const MESSAGE_ID$
|
|
1989
|
+
const MESSAGE_ID$3 = 'no-href-with-router-link';
|
|
1989
1990
|
const ERROR_MESSAGE$1 = 'Do not use href and routerLink attributes together on the same element';
|
|
1990
|
-
const config = {
|
|
1991
|
+
const config$1 = {
|
|
1991
1992
|
create(context) {
|
|
1992
1993
|
return {
|
|
1993
1994
|
Tag(node) {
|
|
@@ -2015,7 +2016,7 @@ const config = {
|
|
|
2015
2016
|
fix: (fixer) => hrefAttribute?.range
|
|
2016
2017
|
? fixer.removeRange(hrefAttribute.range)
|
|
2017
2018
|
: null,
|
|
2018
|
-
messageId: MESSAGE_ID$
|
|
2019
|
+
messageId: MESSAGE_ID$3,
|
|
2019
2020
|
node: (routerLinkAttribute ??
|
|
2020
2021
|
hrefAttribute ??
|
|
2021
2022
|
htmlNode),
|
|
@@ -2027,7 +2028,7 @@ const config = {
|
|
|
2027
2028
|
meta: {
|
|
2028
2029
|
docs: { description: ERROR_MESSAGE$1 },
|
|
2029
2030
|
fixable: 'code',
|
|
2030
|
-
messages: { [MESSAGE_ID$
|
|
2031
|
+
messages: { [MESSAGE_ID$3]: ERROR_MESSAGE$1 },
|
|
2031
2032
|
type: 'problem',
|
|
2032
2033
|
},
|
|
2033
2034
|
};
|
|
@@ -2192,11 +2193,115 @@ function isPlaywrightLocatorType(type) {
|
|
|
2192
2193
|
});
|
|
2193
2194
|
}
|
|
2194
2195
|
|
|
2196
|
+
const MESSAGE_ID$2 = 'no-project-as-in-ng-template';
|
|
2197
|
+
const NESTED_TEMPLATE_MESSAGE_ID = 'no-nested-template-in-dynamic-outlet';
|
|
2198
|
+
const PROJECT_AS_ERROR_MESSAGE = 'ngProjectAs on a dynamic outlet breaks SSR hydration. Use static content projection instead.';
|
|
2199
|
+
const NESTED_TEMPLATE_ERROR_MESSAGE = 'Avoid nesting ng-template inside dynamic outlet containers. Move the template outside the ng-container.';
|
|
2200
|
+
const DYNAMIC_OUTLET_DIRECTIVES = new Set([
|
|
2201
|
+
'ngComponentOutlet',
|
|
2202
|
+
'ngTemplateOutlet',
|
|
2203
|
+
'polymorpheusOutlet',
|
|
2204
|
+
]);
|
|
2205
|
+
function toLoc(span) {
|
|
2206
|
+
return {
|
|
2207
|
+
end: {
|
|
2208
|
+
column: span.end.col,
|
|
2209
|
+
line: span.end.line + 1,
|
|
2210
|
+
},
|
|
2211
|
+
start: {
|
|
2212
|
+
column: span.start.col,
|
|
2213
|
+
line: span.start.line + 1,
|
|
2214
|
+
},
|
|
2215
|
+
};
|
|
2216
|
+
}
|
|
2217
|
+
function isInsideDynamicOutlet(node) {
|
|
2218
|
+
let parent = node.parent;
|
|
2219
|
+
while (parent) {
|
|
2220
|
+
const hasDynamicOutletDirective = parent instanceof TmplAstTemplate &&
|
|
2221
|
+
parent.templateAttrs.some((attr) => DYNAMIC_OUTLET_DIRECTIVES.has(attr.name));
|
|
2222
|
+
if (hasDynamicOutletDirective) {
|
|
2223
|
+
return true;
|
|
2224
|
+
}
|
|
2225
|
+
parent = parent.parent;
|
|
2226
|
+
}
|
|
2227
|
+
return false;
|
|
2228
|
+
}
|
|
2229
|
+
function checkProjectAsOnDynamicOutlet(context, node) {
|
|
2230
|
+
const ngProjectAsAttr = node.attributes.find((attr) => attr.name === 'ngProjectAs') ??
|
|
2231
|
+
node.inputs.find((input) => input.name === 'ngProjectAs');
|
|
2232
|
+
if (ngProjectAsAttr && isInsideDynamicOutlet(node)) {
|
|
2233
|
+
context.report({
|
|
2234
|
+
loc: toLoc(ngProjectAsAttr.sourceSpan),
|
|
2235
|
+
messageId: MESSAGE_ID$2,
|
|
2236
|
+
});
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
function checkNestedTemplateInDynamicOutlet(context, node) {
|
|
2240
|
+
const hasDynamicOutletInput = node.inputs.some((input) => DYNAMIC_OUTLET_DIRECTIVES.has(input.name));
|
|
2241
|
+
if (!hasDynamicOutletInput) {
|
|
2242
|
+
return;
|
|
2243
|
+
}
|
|
2244
|
+
for (const child of node.children) {
|
|
2245
|
+
if (child instanceof TmplAstTemplate && child.tagName === 'ng-template') {
|
|
2246
|
+
context.report({
|
|
2247
|
+
loc: toLoc(child.sourceSpan),
|
|
2248
|
+
messageId: NESTED_TEMPLATE_MESSAGE_ID,
|
|
2249
|
+
});
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
const config = {
|
|
2254
|
+
create(context) {
|
|
2255
|
+
return {
|
|
2256
|
+
Element(rawNode) {
|
|
2257
|
+
const node = rawNode;
|
|
2258
|
+
checkProjectAsOnDynamicOutlet(context, node);
|
|
2259
|
+
checkNestedTemplateInDynamicOutlet(context, node);
|
|
2260
|
+
},
|
|
2261
|
+
};
|
|
2262
|
+
},
|
|
2263
|
+
meta: {
|
|
2264
|
+
docs: { description: PROJECT_AS_ERROR_MESSAGE },
|
|
2265
|
+
messages: {
|
|
2266
|
+
[MESSAGE_ID$2]: PROJECT_AS_ERROR_MESSAGE,
|
|
2267
|
+
[NESTED_TEMPLATE_MESSAGE_ID]: NESTED_TEMPLATE_ERROR_MESSAGE,
|
|
2268
|
+
},
|
|
2269
|
+
schema: [],
|
|
2270
|
+
type: 'problem',
|
|
2271
|
+
},
|
|
2272
|
+
};
|
|
2273
|
+
|
|
2195
2274
|
const createRule$7 = ESLintUtils.RuleCreator((name) => name);
|
|
2275
|
+
function collectArrayExpressions(node) {
|
|
2276
|
+
const result = [];
|
|
2277
|
+
if (node.type === AST_NODE_TYPES.ArrayExpression) {
|
|
2278
|
+
result.push(node);
|
|
2279
|
+
}
|
|
2280
|
+
switch (node.type) {
|
|
2281
|
+
case AST_NODE_TYPES.BinaryExpression:
|
|
2282
|
+
case AST_NODE_TYPES.LogicalExpression:
|
|
2283
|
+
result.push(...collectArrayExpressions(node.left));
|
|
2284
|
+
result.push(...collectArrayExpressions(node.right));
|
|
2285
|
+
break;
|
|
2286
|
+
case AST_NODE_TYPES.ConditionalExpression:
|
|
2287
|
+
result.push(...collectArrayExpressions(node.consequent));
|
|
2288
|
+
result.push(...collectArrayExpressions(node.alternate));
|
|
2289
|
+
break;
|
|
2290
|
+
case AST_NODE_TYPES.ObjectExpression:
|
|
2291
|
+
for (const property of node.properties) {
|
|
2292
|
+
if (property.type === AST_NODE_TYPES.Property) {
|
|
2293
|
+
result.push(...collectArrayExpressions(property.value));
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
break;
|
|
2297
|
+
}
|
|
2298
|
+
return result;
|
|
2299
|
+
}
|
|
2196
2300
|
const rule$5 = createRule$7({
|
|
2197
2301
|
create(context) {
|
|
2198
2302
|
const parserServices = ESLintUtils.getParserServices(context);
|
|
2199
2303
|
const typeChecker = parserServices.program.getTypeChecker();
|
|
2304
|
+
const ignoreTupleContextualTyping = context.options[0]?.ignoreTupleContextualTyping ?? true;
|
|
2200
2305
|
function check(node, typeAnnotation, value) {
|
|
2201
2306
|
if (!typeAnnotation || !value) {
|
|
2202
2307
|
return;
|
|
@@ -2219,6 +2324,19 @@ const rule$5 = createRule$7({
|
|
|
2219
2324
|
!value.returnType) {
|
|
2220
2325
|
return;
|
|
2221
2326
|
}
|
|
2327
|
+
// If the annotation provides contextual typing that narrows an array
|
|
2328
|
+
// literal to a tuple (e.g. [0, 0] → readonly [number, number]), removing
|
|
2329
|
+
// it would widen the inferred type. This covers both direct array literals
|
|
2330
|
+
// and arrays nested inside object literals or conditional expressions.
|
|
2331
|
+
if (ignoreTupleContextualTyping) {
|
|
2332
|
+
const arrayExpressions = collectArrayExpressions(value);
|
|
2333
|
+
for (const arrayExpression of arrayExpressions) {
|
|
2334
|
+
const tsArrayNode = parserServices.esTreeNodeToTSNodeMap.get(arrayExpression);
|
|
2335
|
+
if (typeChecker.isTupleType(typeChecker.getTypeAtLocation(tsArrayNode))) {
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2222
2340
|
// If the initializer is a call to a generic function with no explicit
|
|
2223
2341
|
// type arguments, the type parameters may be inferred from the
|
|
2224
2342
|
// contextual return type provided by this annotation. Removing the
|
|
@@ -2258,7 +2376,18 @@ const rule$5 = createRule$7({
|
|
|
2258
2376
|
messages: {
|
|
2259
2377
|
redundantTypeAnnotation: 'Type annotation is redundant — the type is already inferred from the initializer',
|
|
2260
2378
|
},
|
|
2261
|
-
schema: [
|
|
2379
|
+
schema: [
|
|
2380
|
+
{
|
|
2381
|
+
additionalProperties: false,
|
|
2382
|
+
properties: {
|
|
2383
|
+
ignoreTupleContextualTyping: {
|
|
2384
|
+
description: 'Preserve annotations when they provide contextual typing that narrows an array literal to a tuple type. Defaults to true.',
|
|
2385
|
+
type: 'boolean',
|
|
2386
|
+
},
|
|
2387
|
+
},
|
|
2388
|
+
type: 'object',
|
|
2389
|
+
},
|
|
2390
|
+
],
|
|
2262
2391
|
type: 'suggestion',
|
|
2263
2392
|
},
|
|
2264
2393
|
name: 'no-redundant-type-annotation',
|
|
@@ -3621,16 +3750,17 @@ const plugin = {
|
|
|
3621
3750
|
version: pkg.version,
|
|
3622
3751
|
},
|
|
3623
3752
|
rules: {
|
|
3624
|
-
'array-as-const': config$
|
|
3753
|
+
'array-as-const': config$3,
|
|
3625
3754
|
'class-property-naming': classPropertyNaming,
|
|
3626
|
-
'decorator-key-sort': config$
|
|
3755
|
+
'decorator-key-sort': config$2,
|
|
3627
3756
|
'flat-exports': flatExports,
|
|
3628
3757
|
'injection-token-description': rule$9,
|
|
3629
3758
|
'no-deep-imports': rule$8,
|
|
3630
3759
|
'no-deep-imports-to-indexed-packages': noDeepImportsToIndexedPackages,
|
|
3631
|
-
'no-href-with-router-link': config,
|
|
3760
|
+
'no-href-with-router-link': config$1,
|
|
3632
3761
|
'no-implicit-public': rule$7,
|
|
3633
3762
|
'no-playwright-empty-fill': rule$6,
|
|
3763
|
+
'no-project-as-in-ng-template': config,
|
|
3634
3764
|
'no-redundant-type-annotation': rule$5,
|
|
3635
3765
|
'no-string-literal-concat': rule$4,
|
|
3636
3766
|
'object-single-line': rule$3,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taiga-ui/eslint-plugin-experience-next",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.460.0",
|
|
4
4
|
"description": "An ESLint plugin to enforce a consistent code styles across taiga-ui projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,23 +27,23 @@
|
|
|
27
27
|
],
|
|
28
28
|
"type": "module",
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@typescript-eslint/rule-tester": "8.58.
|
|
30
|
+
"@typescript-eslint/rule-tester": "8.58.1",
|
|
31
31
|
"glob": "13.0.6"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@eslint/compat": "^2.0.
|
|
34
|
+
"@eslint/compat": "^2.0.5",
|
|
35
35
|
"@eslint/markdown": "^8.0.1",
|
|
36
36
|
"@html-eslint/eslint-plugin": "^0.59.0",
|
|
37
37
|
"@html-eslint/parser": "^0.59.0",
|
|
38
38
|
"@smarttools/eslint-plugin-rxjs": "^1.0.22",
|
|
39
39
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
40
40
|
"@types/glob": "*",
|
|
41
|
-
"@typescript-eslint/eslint-plugin": "^8.58.
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^8.58.1",
|
|
42
42
|
"angular-eslint": "^20.7.0",
|
|
43
43
|
"eslint": "^9.39.2",
|
|
44
44
|
"eslint-config-prettier": "^10.1.7",
|
|
45
45
|
"eslint-plugin-compat": "^7.0.1",
|
|
46
|
-
"eslint-plugin-cypress": "^6.
|
|
46
|
+
"eslint-plugin-cypress": "^6.3.0",
|
|
47
47
|
"eslint-plugin-de-morgan": "^2.1.1",
|
|
48
48
|
"eslint-plugin-decorator-position": "^6.0.0",
|
|
49
49
|
"eslint-plugin-file-progress": "^3.0.2",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
62
62
|
"glob": "*",
|
|
63
63
|
"globals": "^17.4.0",
|
|
64
|
-
"typescript-eslint": "^8.58.
|
|
64
|
+
"typescript-eslint": "^8.58.1"
|
|
65
65
|
},
|
|
66
66
|
"publishConfig": {
|
|
67
67
|
"access": "public"
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
-
|
|
2
|
+
type Options = [
|
|
3
|
+
{
|
|
4
|
+
ignoreTupleContextualTyping?: boolean;
|
|
5
|
+
}?
|
|
6
|
+
];
|
|
7
|
+
export declare const rule: ESLintUtils.RuleModule<"redundantTypeAnnotation", Options, unknown, ESLintUtils.RuleListener> & {
|
|
3
8
|
name: string;
|
|
4
9
|
};
|
|
5
10
|
export default rule;
|