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 spacesExpressions
${} 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.