Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f8db925

Browse filesBrowse files
fix(eslint-plugin): [consistent-indexed-object-style] check for indirect circular types in aliased mapped types (typescript-eslint#11177)
* initial implementation * add tests * use existing logic * remove unrelated code * remove unrelated changes * don't check type constraints in mapped types --------- Co-authored-by: Josh Goldberg <git@joshuakgoldberg.com>
1 parent fdbdbab commit f8db925
Copy full SHA for f8db925

File tree

Expand file treeCollapse file tree

2 files changed

+52
-5
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+52
-5
lines changed

‎packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts

Copy file name to clipboardExpand all lines: packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts
+10-5Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,10 @@ export default createRule<Options, MessageIds>({
205205
const scope = context.sourceCode.getScope(key);
206206
const superVar = ASTUtils.findVariable(scope, parentId.name);
207207
if (superVar) {
208-
const isCircular = superVar.references.some(
209-
item =>
210-
item.isTypeReference &&
211-
node.range[0] <= item.identifier.range[0] &&
212-
node.range[1] >= item.identifier.range[1],
208+
const isCircular = isDeeplyReferencingType(
209+
node.parent,
210+
superVar,
211+
new Set([parentId]),
213212
);
214213
if (isCircular) {
215214
return;
@@ -291,6 +290,12 @@ function isDeeplyReferencingType(
291290
return [node.indexType, node.objectType].some(type =>
292291
isDeeplyReferencingType(type, superVar, visited),
293292
);
293+
case AST_NODE_TYPES.TSMappedType:
294+
if (node.typeAnnotation) {
295+
return isDeeplyReferencingType(node.typeAnnotation, superVar, visited);
296+
}
297+
298+
break;
294299
case AST_NODE_TYPES.TSConditionalType:
295300
return [
296301
node.checkType,

‎packages/eslint-plugin/tests/rules/consistent-indexed-object-style.test.ts

Copy file name to clipboardExpand all lines: packages/eslint-plugin/tests/rules/consistent-indexed-object-style.test.ts
+42Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,18 @@ interface ExampleObject {
174174
[key: string]: ExampleRoot;
175175
}
176176
`,
177+
`
178+
type Bar<K extends string = never> = {
179+
[k in K]: Bar;
180+
};
181+
`,
182+
`
183+
type Bar<K extends string = never> = {
184+
[k in K]: Foo;
185+
};
186+
187+
type Foo = Bar;
188+
`,
177189

178190
// Type literal
179191
'type Foo = {};',
@@ -646,6 +658,36 @@ type Foo2 = Record<string, Foo3>;
646658
type Foo3 = Record<string, Record<string, Foo1>>;
647659
`,
648660
},
661+
{
662+
code: `
663+
type Foos<K extends string = never> = {
664+
[k in K]: { foo: Foo };
665+
};
666+
667+
type Foo = Foos;
668+
`,
669+
errors: [{ column: 39, line: 2, messageId: 'preferRecord' }],
670+
output: `
671+
type Foos<K extends string = never> = Record<K, { foo: Foo }>;
672+
673+
type Foo = Foos;
674+
`,
675+
},
676+
{
677+
code: `
678+
type Foos<K extends string = never> = {
679+
[k in K]: Foo[];
680+
};
681+
682+
type Foo = Foos;
683+
`,
684+
errors: [{ column: 39, line: 2, messageId: 'preferRecord' }],
685+
output: `
686+
type Foos<K extends string = never> = Record<K, Foo[]>;
687+
688+
type Foo = Foos;
689+
`,
690+
},
649691

650692
// Generic
651693
{

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.