diff --git a/packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts b/packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts index c1b86bf8c61..bd48718c68b 100644 --- a/packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts +++ b/packages/eslint-plugin/src/rules/consistent-indexed-object-style.ts @@ -101,10 +101,10 @@ export default createRule({ fix(fixer) { const key = sourceCode.getText(keyType.typeAnnotation); const value = sourceCode.getText(valueType.typeAnnotation); - return fixer.replaceText( - node, - `${prefix}Record<${key}, ${value}>${postfix}`, - ); + const record = member.readonly + ? `Readonly>` + : `Record<${key}, ${value}>`; + return fixer.replaceText(node, `${prefix}${record}${postfix}`); }, }); } diff --git a/packages/eslint-plugin/tests/rules/consistent-indexed-object-style.test.ts b/packages/eslint-plugin/tests/rules/consistent-indexed-object-style.test.ts index ebedccf424a..31077fcf620 100644 --- a/packages/eslint-plugin/tests/rules/consistent-indexed-object-style.test.ts +++ b/packages/eslint-plugin/tests/rules/consistent-indexed-object-style.test.ts @@ -140,6 +140,19 @@ type Foo = Record; errors: [{ messageId: 'preferRecord', line: 2, column: 1 }], }, + // Readonly interface + { + code: ` +interface Foo { + readonly [key: string]: any; +} + `, + output: ` +type Foo = Readonly>; + `, + errors: [{ messageId: 'preferRecord', line: 2, column: 1 }], + }, + // Interface with generic parameter { code: ` @@ -153,6 +166,19 @@ type Foo = Record; errors: [{ messageId: 'preferRecord', line: 2, column: 1 }], }, + // Readonly interface with generic parameter + { + code: ` +interface Foo { + readonly [key: string]: A; +} + `, + output: ` +type Foo = Readonly>; + `, + errors: [{ messageId: 'preferRecord', line: 2, column: 1 }], + }, + // Interface with multiple generic parameters { code: ` @@ -166,6 +192,19 @@ type Foo = Record; errors: [{ messageId: 'preferRecord', line: 2, column: 1 }], }, + // Readonly interface with multiple generic parameters + { + code: ` +interface Foo { + readonly [key: A]: B; +} + `, + output: ` +type Foo = Readonly>; + `, + errors: [{ messageId: 'preferRecord', line: 2, column: 1 }], + }, + // Type literal { code: 'type Foo = { [key: string]: any };', @@ -173,6 +212,13 @@ type Foo = Record; errors: [{ messageId: 'preferRecord', line: 1, column: 12 }], }, + // Readonly type literal + { + code: 'type Foo = { readonly [key: string]: any };', + output: 'type Foo = Readonly>;', + errors: [{ messageId: 'preferRecord', line: 1, column: 12 }], + }, + // Generic { code: 'type Foo = Generic<{ [key: string]: any }>;', @@ -180,6 +226,13 @@ type Foo = Record; errors: [{ messageId: 'preferRecord', line: 1, column: 20 }], }, + // Readonly Generic + { + code: 'type Foo = Generic<{ readonly [key: string]: any }>;', + output: 'type Foo = Generic>>;', + errors: [{ messageId: 'preferRecord', line: 1, column: 20 }], + }, + // Function types { code: 'function foo(arg: { [key: string]: any }) {}', @@ -192,6 +245,18 @@ type Foo = Record; errors: [{ messageId: 'preferRecord', line: 1, column: 17 }], }, + // Readonly function types + { + code: 'function foo(arg: { readonly [key: string]: any }) {}', + output: 'function foo(arg: Readonly>) {}', + errors: [{ messageId: 'preferRecord', line: 1, column: 19 }], + }, + { + code: 'function foo(): { readonly [key: string]: any } {}', + output: 'function foo(): Readonly> {}', + errors: [{ messageId: 'preferRecord', line: 1, column: 17 }], + }, + // Never // Type literal {