Skip to main content

Command Palette

Search for a command to run...

Template Literals in JavaScript: Write Cleaner Strings

Published
5 min read
Template Literals in JavaScript: Write Cleaner Strings
S
Full-stack developer obsessed with performance, scalability, and clean systems. I use Arch btw.

Introduction

String handling in JavaScript used to be one of those things you just accepted as annoying. You had + operators scattered everywhere, escaped quotes inside quotes, and multi-line strings that looked like someone had an argument with their keyboard. Then ES6 came along and fixed most of it in one go.


The Problem With Old-School Concatenation

Here is a typical piece of pre-ES6 code that builds a greeting:

var name = "Priya";
var age = 28;
var city = "Mumbai";

var message = "Hello, my name is " + name + ". I am " + age + " years old and I live in " + city + ".";

It works. It also looks like you assembled it with scotch tape. Every string segment needs its own quote pair, and every variable needs its own + on each side. Miss one space and you get "I am28years old". Add a variable mid-sentence and you are counting plus signs to make sure you have the right number.

Multi-line strings were worse:

var html = "<div class='card'>" +
    "<h2>" + title + "</h2>" +
    "<p>" + description + "</p>" +
    "</div>";

This is technically fine but reading it is a chore. You have to mentally strip the quotes and plus signs to understand the actual structure.


Template Literal Syntax

Template literals use backticks instead of single or double quotes:

const greeting = `Hello, world`;

That alone changes nothing. The power comes from two features built on top of that syntax: interpolation and native multi-line support.


Embedding Variables Directly in Strings

Inside a template literal, you can drop any JavaScript expression directly into the string using ${}:

const name = "Priya";
const age = 28;
const city = "Mumbai";

const message = `Hello, my name is \({name}. I am \){age} years old and I live in ${city}.`;

The string reads exactly like it will appear at runtime. No plus signs, no closing and reopening quotes. You just write the sentence and put variables where they belong.

The ${} syntax accepts any valid JavaScript expression, not just variables:

const price = 450;
const quantity = 3;

console.log(`Total: ${price * quantity} rupees`);
// Total: 1350 rupees
const user = { name: "Arjun", role: "admin" };

console.log(`Welcome, \({user.name}. Your role is \){user.role}.`);
// Welcome, Arjun. Your role is admin.
const score = 72;

console.log(`Result: ${score >= 60 ? "Pass" : "Fail"}`);
// Result: Pass

Ternaries, method calls, object properties, arithmetic, all of it works inside ${} without any extra setup.


Multi-Line Strings Without the Mess

With regular strings, a newline inside quotes is a syntax error. The old workaround was \n or concatenating across lines:

// Old way
var poem = "Line one\n" +
    "Line two\n" +
    "Line three";

Template literals preserve whitespace and line breaks naturally:

const poem = `Line one
Line two
Line three`;

What you type is what you get. This makes building HTML fragments or multi-line output much more readable:

const card = `
    <div class="card">
        <h2>${title}</h2>
        <p>${description}</p>
        <span class="tag">${category}</span>
    </div>
`;

Compare that to the concatenation version from earlier and the difference is obvious. The structure is visible. You can read it like HTML.


Where Template Literals Actually Show Up

Building URLs and query strings

const baseUrl = "https://api.example.com";
const userId = 42;
const endpoint = `\({baseUrl}/users/\){userId}/orders`;

Before: baseUrl + "/users/" + userId + "/orders". The template version is just clearer.

Constructing SQL or query strings

const table = "products";
const limit = 10;

const query = `SELECT * FROM \({table} WHERE active = true LIMIT \){limit}`;

Generating error messages

function divide(a, b) {
    if (b === 0) {
        throw new Error(`Cannot divide ${a} by zero`);
    }
    return a / b;
}

Logging with context

console.log(`[\({new Date().toISOString()}] User \){userId} logged in from ${ip}`);

React and JSX (or template-based rendering)

Template literals come up a lot in dynamic class names and inline styles:

const className = `btn \({isActive ? "btn-primary" : "btn-secondary"} \){isDisabled ? "disabled" : ""}`;

Tagged Templates

Tagged templates are an advanced form of template literals. You place a function name directly before the backtick, and that function gets to control what the template produces:

function tag(strings, ...values) {
    console.log(strings);   // ["Hello, ", "!"]
    console.log(values);    // ["Sameer"]
}

tag`Hello, ${"Sameer"}!`;

The tag function receives the static string parts as an array and the interpolated values as separate arguments. Whatever the function returns becomes the final value.

A simple practical use is highlighting dynamic values for debugging:

function highlight(strings, ...values) {
    return strings.reduce((result, str, i) => {
        const val = values[i] !== undefined ? `[${values[i]}]` : "";
        return result + str + val;
    }, "");
}

const user = "Arjun";
const score = 94;

console.log(highlight`Student \({user} scored \){score} marks.`);
// Student [Arjun] scored [94] marks.

A Side-by-Side Comparison

Before:

function greet(user) {
    return "Hello, " + user.name + "! You have " + user.messages + " unread message" + (user.messages === 1 ? "" : "s") + ".";
}

After:

function greet(user) {
    const plural = user.messages === 1 ? "" : "s";
    return `Hello, \({user.name}! You have \){user.messages} unread message${plural}.`;
}

The second version takes less mental energy to parse. You can see the sentence structure without untangling the concatenation logic.


Conclusion

Template literals are one of those features that feels minor until you use it for a week and then cannot imagine going back. The code you write is closer to the output you intend, and that gap matters when you are reading code three months after you wrote it.