Skip to content

Commit

Permalink
fix(eslint-plugin): [consistent-indexed-object-style] do not report f…
Browse files Browse the repository at this point in the history
…or circular references (#4347)
  • Loading branch information
armano2 committed Dec 27, 2021
1 parent ba0b1e3 commit 6edebcd
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 2 deletions.
Expand Up @@ -34,7 +34,8 @@ export default createRule<Options, MessageIds>({

function checkMembers(
members: TSESTree.TypeElement[],
node: TSESTree.Node,
node: TSESTree.TSTypeLiteral | TSESTree.TSInterfaceDeclaration,
parentId: TSESTree.Identifier | undefined,
prefix: string,
postfix: string,
safeFix = true,
Expand Down Expand Up @@ -67,6 +68,22 @@ export default createRule<Options, MessageIds>({
return;
}

if (parentId) {
const scope = context.getScope();
const superVar = scope.set.get(parentId.name);
if (superVar) {
const isCircular = superVar.references.some(
item =>
item.isTypeReference &&
node.range[0] <= item.identifier.range[0] &&
node.range[1] >= item.identifier.range[1],
);
if (isCircular) {
return;
}
}
}

context.report({
node,
messageId: 'preferRecord',
Expand Down Expand Up @@ -112,7 +129,8 @@ export default createRule<Options, MessageIds>({
}),
...(mode === 'record' && {
TSTypeLiteral(node): void {
checkMembers(node.members, node, '', '');
const parent = findParentDeclaration(node);
checkMembers(node.members, node, parent?.id, '', '');
},
TSInterfaceDeclaration(node): void {
let genericTypes = '';
Expand All @@ -126,6 +144,7 @@ export default createRule<Options, MessageIds>({
checkMembers(
node.body.body,
node,
node.id,
`type ${node.id.name}${genericTypes} = `,
';',
!node.extends?.length,
Expand All @@ -135,3 +154,15 @@ export default createRule<Options, MessageIds>({
};
},
});

function findParentDeclaration(
node: TSESTree.Node,
): TSESTree.TSTypeAliasDeclaration | undefined {
if (node.parent && node.parent.type !== AST_NODE_TYPES.TSTypeAnnotation) {
if (node.parent.type === AST_NODE_TYPES.TSTypeAliasDeclaration) {
return node.parent;
}
return findParentDeclaration(node.parent);
}
return undefined;
}
Expand Up @@ -30,6 +30,15 @@ interface Foo {
bar: string;
}
`,
// circular
'type Foo = { [key: string]: string | Foo };',
'type Foo = { [key: string]: Foo };',
'type Foo = { [key: string]: Foo } | Foo;',
`
interface Foo {
[key: string]: Foo;
}
`,

// Type literal
'type Foo = {};',
Expand Down Expand Up @@ -287,6 +296,52 @@ type Foo<A, B> = Readonly<Record<A, B>>;
errors: [{ messageId: 'preferIndexSignature', line: 1, column: 15 }],
},

// Circular
{
code: 'type Foo = { [k: string]: A.Foo };',
output: 'type Foo = Record<string, A.Foo>;',
errors: [{ messageId: 'preferRecord', line: 1, column: 12 }],
},
{
code: 'type Foo = { [key: string]: AnotherFoo };',
output: 'type Foo = Record<string, AnotherFoo>;',
errors: [{ messageId: 'preferRecord', line: 1, column: 12 }],
},
{
code: 'type Foo = { [key: string]: { [key: string]: Foo } };',
output: 'type Foo = { [key: string]: Record<string, Foo> };',
errors: [{ messageId: 'preferRecord', line: 1, column: 29 }],
},
{
code: 'type Foo = { [key: string]: string } | Foo;',
output: 'type Foo = Record<string, string> | Foo;',
errors: [{ messageId: 'preferRecord', line: 1, column: 12 }],
},
{
code: `
interface Foo {
[k: string]: A.Foo;
}
`,
output: `
type Foo = Record<string, A.Foo>;
`,
errors: [{ messageId: 'preferRecord', line: 2, column: 1 }],
},
{
code: `
interface Foo {
[k: string]: { [key: string]: Foo };
}
`,
output: `
interface Foo {
[k: string]: Record<string, Foo>;
}
`,
errors: [{ messageId: 'preferRecord', line: 3, column: 16 }],
},

// Generic
{
code: 'type Foo = Generic<Record<string, any>>;',
Expand Down

0 comments on commit 6edebcd

Please sign in to comment.