Skip to main content
ESLint Interlace
Plugin: modernizationRules

prefer-template-literal

Prefer template literals over string concatenation with runtime values

Keywords: template literal, string concatenation, plus operator, interpolation, ESLint rule, ES2015, auto-fix, LLM-optimized

Prefer template literals over string concatenation with + when at least one operand is a runtime value. This rule is part of eslint-plugin-modernization.

Quick Summary

AspectDetails
SeverityWarning (modern JavaScript)
Auto-Fix✅ Yes (replaces + chain with a template literal)
CategoryModernization
ESLint MCP✅ Optimized for ESLint MCP integration
Best ForES2015+ codebases, cleaner string building

Rule Details

Template literals with string interpolation are more readable and less error-prone than concatenating strings with +. This rule flags any + expression that mixes string literals with runtime values (variables, member expressions, function calls, etc.) and rewrites the entire chain as a single template literal.

Pure string-literal concatenation ("foo" + "bar") and numeric addition (1 + 2) are intentionally ignored.

Why This Matters

IssueImpactSolution
📖 ReadabilityMixed + chains are hard to scanUse template literals with interpolation
🐛 Implicit coercion+ coerces operands unpredictablyInterpolation is unambiguous
🔄 ConsistencyMultiple string-building styles in codebaseStandardize on template literals

Examples

❌ Incorrect

// String concatenation with runtime value
const greeting = "Hello, " + name + "!";
const path = "/api/v1/" + resource + "/" + id;
const message = "Error: " + err.message;

✅ Correct

// Template literal with interpolation
const greeting = `Hello, ${name}!`;
const path = `/api/v1/${resource}/${id}`;
const message = `Error: ${err.message}`;
// Pure string concat is fine (no runtime values)
const url = "https://" + "example.com";

Auto-fix

ESLint can fix this automatically. Running eslint --fix rewrites the concatenation chain into a single template literal — no manual edits required.

Before

const msg = "Hello, " + name + "!";
const path = "/api/v1/" + resource + "/" + id;

After

const msg = `Hello, ${name}!`;
const path = `/api/v1/${resource}/${id}`;

The fixer joins all operands into one template literal, promoting any plain string segments to static parts and wrapping runtime values in ${...} expressions.

Configuration Examples

Basic Usage

{
  rules: {
    'modernization/prefer-template-literal': 'warn'
  }
}

Further Reading

Known False Negatives

The following patterns are not detected due to static analysis limitations:

Dynamic Variable References

Why: Static analysis cannot always determine whether a variable holds a string or a number at the point of + use.

// ❌ NOT DETECTED - ambiguous operand type
const result = a + b; // could be numeric addition

Mitigation: Add TypeScript types so the linter has enough signal, or review concatenation chains manually.

Imported Values

Why: When values come from imports, the rule cannot analyze their origin or construction.

// ❌ NOT DETECTED - Value from import
import { prefix } from './constants';
const path = prefix + resource; // Cross-file origin not tracked

Mitigation: Ensure imported string values are typed as string in TypeScript so the rule can flag the concatenation.