JavaScript Template Literals and Tagged Templates

JavaScript template literals offer a modern, flexible way to work with strings using backticks, enabling features like multi-line text and embedded expressions. Beyond basic string interpolation, template literals support an advanced feature known as tagged templates, which allows developers to parse and transform string literals using custom functions. This guide covers how standard template literals work, the mechanics of tagged templates, and their practical real-world applications.

Understanding JavaScript Template Literals

Introduced in ECMAScript 2015 (ES6), template literals are string literals delimited by backtick characters (`) instead of single or double quotes. They simplify string creation by removing the need for traditional concatenation and complex escape sequences.

Core Features

  1. String Interpolation: Expressions are embedded inside strings using the ${expression} syntax. Any valid JavaScript expression, including variables, calculations, or function calls, can be evaluated inside the placeholder.
const name = "Alice";
const score = 95;
console.log(`Student ${name} scored ${score + 5}/100.`);
// Output: Student Alice scored 100/100.
  1. Multi-line Strings: Newlines inside backticks are preserved automatically without requiring the \n escape character.
const message = `This is a string
that spans across
multiple lines.`;

How Tagged Templates Work

Tagged templates represent a more advanced form of template literals. By prefixing a template literal with a function name (the “tag”), the function is invoked with the parsed components of the template literal rather than producing a plain string directly.

The Tag Function Signature

A tag function receives: 1. An array of static string segments: An array containing the string pieces split around the interpolated expressions. 2. Subsequent arguments: The evaluated values of each embedded expression, commonly gathered using rest parameters (...values).

function myTag(strings, ...values) {
  console.log(strings);
  console.log(values);
}

const item = "apples";
const count = 5;

myTag`I have ${count} ${item}.`;
// strings: ['I have ', ' ', '.']
// values: [5, 'apples']

The strings array will always contain one more element than the number of interpolated values.

Constructing Custom Output

A tag function can process the inputs and return any type of data—such as a modified string, a DOM element, or a structured object.

function highlight(strings, ...values) {
  return strings.reduce((acc, str, i) => {
    const value = values[i] ? `<mark>${values[i]}</mark>` : "";
    return `${acc}${str}${value}`;
  }, "");
}

const user = "Alex";
const action = "logged in";
const result = highlight`User ${user} has ${action}.`;

console.log(result);
// Output: User <mark>Alex</mark> has <mark>logged in</mark>.

Advanced Feature: The raw Property

The first argument passed to a tag function contains a special raw property (strings.raw). This allows access to the raw strings as they were written, without processing escape sequences like \n or \t.

function showRaw(strings) {
  console.log(strings.raw[0]);
}

showRaw`Line 1\nLine 2`;
// Output: Line 1\nLine 2 (literal backslash and 'n', not a newline)

JavaScript also provides the built-in String.raw tag function to create raw strings directly:

const filePath = String.raw`C:\Development\new_project`;
// Output: C:\Development\new_project

Common Use Cases for Tagged Templates