@@ -109,6 +109,20 @@ function getNonNumericOperand(node) {
109109 return null ;
110110}
111111
112+ /**
113+ * Checks whether an expression evaluates to a string.
114+ * @param {ASTNode } node node that represents the expression to check.
115+ * @returns {boolean } Whether or not the expression evaluates to a string.
116+ */
117+ function isStringType ( node ) {
118+ return astUtils . isStringLiteral ( node ) ||
119+ (
120+ node . type === "CallExpression" &&
121+ node . callee . type === "Identifier" &&
122+ node . callee . name === "String"
123+ ) ;
124+ }
125+
112126/**
113127 * Checks whether a node is an empty string literal or not.
114128 * @param {ASTNode } node The node to check.
@@ -126,8 +140,8 @@ function isEmptyString(node) {
126140 */
127141function isConcatWithEmptyString ( node ) {
128142 return node . operator === "+" && (
129- ( isEmptyString ( node . left ) && ! astUtils . isStringLiteral ( node . right ) ) ||
130- ( isEmptyString ( node . right ) && ! astUtils . isStringLiteral ( node . left ) )
143+ ( isEmptyString ( node . left ) && ! isStringType ( node . right ) ) ||
144+ ( isEmptyString ( node . right ) && ! isStringType ( node . left ) )
131145 ) ;
132146}
133147
@@ -332,6 +346,11 @@ module.exports = {
332346 return ;
333347 }
334348
349+ // if the expression is already a string, then this isn't a coercion
350+ if ( isStringType ( node . expressions [ 0 ] ) ) {
351+ return ;
352+ }
353+
335354 const code = sourceCode . getText ( node . expressions [ 0 ] ) ;
336355 const recommendation = `String(${ code } )` ;
337356
0 commit comments