Template Literals

Backtick strings with embedded expressions, multiline support, and tagged templates.

Interpolation

Embed variables directly in strings with ${}.

// Old way — string concatenation:
const name = "Alice";
const greeting = "Hello, " + name + "!"; // "Hello, Alice!"

// Template literal — use backticks (`):
const greeting2 = `Hello, ${name}!`; // "Hello, Alice!"

// Embed any variable:
const age = 25;
const city = "Tokyo";
const bio = `${name} is ${age} years old and lives in ${city}.`;
// "Alice is 25 years old and lives in Tokyo."

// Works with all types:
const items = 3;
const price = 9.99;
const msg = `${items} items cost $${(items * price).toFixed(2)}`;
// "3 items cost $29.97"

Multiline Strings

Write strings that span multiple lines without \\n.

// Old way — escape characters:
const old = "Line 1\nLine 2\nLine 3";

// Template literal — just press Enter:
const poem = `Roses are red,
Violets are blue,
Template literals
Are awesome too.`;

// Great for HTML:
const card = `
  <div class="card">
    <h2>${title}</h2>
    <p>${description}</p>
  </div>
`;

// ⚠️ Whitespace is preserved exactly:
const indented = `
    This has 4 spaces before it.
    So does this line.
`;
// First char is a newline, each line has 4 leading spaces

Expressions

${} can contain any JavaScript expression.

// Math:
const total = `Total: $${(price * 1.2).toFixed(2)}`;

// Ternary:
const status = `User is ${age >= 18 ? "adult" : "minor"}`;

// Function calls:
const upper = `Name: ${name.toUpperCase()}`;
const len = `Length: ${items.length}`;

// Method chains:
const slug = `/posts/${title.toLowerCase().replace(/ /g, "-")}`;

Any valid JS expression works inside ${}. The result is converted to a string.

1 / 2

Tagged Templates

Process template literals with a custom function.

// A tag is a function that processes the template:
function highlight(strings, ...values) {
  // strings = array of static parts
  // values = array of interpolated values
  return strings.reduce((result, str, i) => {
    return result + str + (values[i] ? `<mark>${values[i]}</mark>` : "");
  }, "");
}

const name = "Alice";
const role = "admin";
highlight`User ${name} has role ${role}`;
// "User <mark>Alice</mark> has role <mark>admin</mark>"

// strings: ["User ", " has role ", ""]
// values: ["Alice", "admin"]
// Real-world: SQL escaping (prevent injection)
function sql(strings, ...values) {
  return {
    text: strings.join("$" + "n"),  // parameterized
    values: values                   // separate values
  };
}
const id = "1; DROP TABLE users";
const query = sql`SELECT * FROM users WHERE id = ${id}`;
// { text: "SELECT * FROM users WHERE id = $n", values: ["1; DROP TABLE users"] }
// Value is safely parameterized, not injected!

// Popular libraries using tagged templates:
// - styled-components: styled.div`color: ${color}`
// - GraphQL: gql`query { user { name } }`
// - lit-html: html`<div>${content}</div>`

Practical Uses

Common patterns with template literals.

// 1. URL construction:
const endpoint = `${BASE_URL}/api/users/${userId}/posts?page=${page}`;

// 2. Error messages:
throw new Error(
  `Expected ${expected} but got ${actual} at index ${i}`
);

// 3. Logging:
console.log(`[${new Date().toISOString()}] ${level}: ${message}`);

// 4. Regex with comments (using String.raw):
const pattern = new RegExp(String.raw`
  ^                  # start
  [a-zA-Z0-9.]+     # username
  @                  # at symbol
  [a-zA-Z0-9]+      # domain
  \.                # dot
  [a-zA-Z]{2,}      # TLD
  $                  # end
`.replace(/\s+#.*$/gm, "").replace(/\s+/g, ""));

// 5. CSS-in-JS:
const styles = `
  .container {
    max-width: ${maxWidth}px;
    padding: ${spacing}rem;
    color: ${theme.text};
  }
`;

FAQ

Common questions about template literals.