diff --git a/packages/eslint-plugin/src/rules/array-type.ts b/packages/eslint-plugin/src/rules/array-type.ts index b9977618c40c..0ed4266a240d 100644 --- a/packages/eslint-plugin/src/rules/array-type.ts +++ b/packages/eslint-plugin/src/rules/array-type.ts @@ -146,7 +146,8 @@ export default util.createRule({ return false; } - if (node.range[0] - prevToken.range[1] > 0) { + const nextToken = sourceCode.getTokenAfter(prevToken); + if (nextToken && sourceCode.isSpaceBetweenTokens(prevToken, nextToken)) { return false; } @@ -168,6 +169,21 @@ export default util.createRule({ return 'T'; } + /** + * @param node the node to be evaluated + */ + function getTypeOpNodeRange( + node: TSESTree.Node | null, + ): [number, number] | undefined { + if (!node) { + return undefined; + } + + const firstToken = sourceCode.getFirstToken(node)!; + const nextToken = sourceCode.getTokenAfter(firstToken)!; + return [firstToken.range[0], nextToken.range[0]]; + } + return { TSArrayType(node): void { if ( @@ -208,24 +224,27 @@ export default util.createRule({ type: getMessageType(node.elementType), }, fix(fixer) { - const startText = requireWhitespaceBefore(node); const toFix = [ fixer.replaceTextRange([node.range[1] - 2, node.range[1]], '>'), - fixer.insertTextBefore( - node, - `${startText ? ' ' : ''}${isReadonly ? 'Readonly' : ''}Array<`, - ), ]; - if (typeOpNode) { - // remove the readonly operator if it exists - toFix.unshift( - fixer.removeRange([ - typeOpNode.range[0], - typeOpNode.range[0] + 'readonly '.length, - ]), + const startText = requireWhitespaceBefore(node); + const typeOpNodeRange = getTypeOpNodeRange(typeOpNode); + + if (typeOpNodeRange) { + toFix.unshift(fixer.removeRange(typeOpNodeRange)); + } else { + toFix.push( + fixer.insertTextBefore(node, `${startText ? ' ' : ''}`), ); } + toFix.push( + fixer.insertTextBefore( + node, + `${isReadonly ? 'Readonly' : ''}Array<`, + ), + ); + if (node.elementType.type === AST_NODE_TYPES.TSParenthesizedType) { const first = sourceCode.getFirstToken(node.elementType); const last = sourceCode.getLastToken(node.elementType); diff --git a/packages/eslint-plugin/tests/rules/array-type.test.ts b/packages/eslint-plugin/tests/rules/array-type.test.ts index 32de7e32c892..86cb1940826b 100644 --- a/packages/eslint-plugin/tests/rules/array-type.test.ts +++ b/packages/eslint-plugin/tests/rules/array-type.test.ts @@ -1071,5 +1071,35 @@ class Foo extends Bar implements Baz { `let a: readonly Array[] = []`, 'array', ); + testOutput( + 'generic', + `type T = readonly(string)[]`, + `type T = ReadonlyArray`, + 'generic', + ); + testOutput( + 'generic', + `let a: readonly(readonly string[])[] = []`, + `let a: ReadonlyArray> = []`, + 'generic', + ); + testOutput( + 'generic', + `type T = readonly(readonly string[])[]`, + `type T = ReadonlyArray>`, + 'generic', + ); + testOutput( + 'generic', + `type T = readonly (readonly string[])[]`, + `type T = ReadonlyArray>`, + 'generic', + ); + testOutput( + 'generic', + `type T = readonly (readonly string[])[]`, + `type T = ReadonlyArray>`, + 'generic', + ); }); });