Tagged Template Literals in JavaScript

Introduction

A tag function runs before the template literal is finalized. It receives string cooked parts and expression values, then returns any value—often a formatted string or a styled DOM node. This builds on template strings and powers libraries like styled-components and i18n helpers.

Prerequisites

How Tag Functions Work

javascript
// Tag receives strings array + expression values
function upperTag(strings, ...values) {
  return strings.reduce((result, str, i) => {
    const val = values[i] ?? "";
    return result + str + String(val).toUpperCase();
  }, "");
}
 
const name = "ada";
const line = upperTag`Hello, ${name}!`;
 
console.log(line);

First argument: array of literal segments (including raw in strings.raw).

Simple HTML Escaper (Concept)

javascript
// Escape < for demo safety in HTML snippets
function safeHtml(strings, ...values) {
  const escape = (s) =>
    String(s)
      .replaceAll("&", "&amp;")
      .replaceAll("<", "&lt;")
      .replaceAll(">", "&gt;");
 
  return strings.reduce(
    (out, str, i) => out + str + escape(values[i] ?? ""),
    ""
  );
}
 
const userInput = "<script>";
const html = safeHtml`<p>Comment: ${userInput}</p>`;
console.log(html);

Real apps use trusted templates or framework escaping—never roll your own security alone.

Styled Output Pattern

javascript
// Return object instead of string
function css(strings, ...values) {
  const style = strings.join("") + values.join("");
  return { className: "dynamic", style };
}
 
const color = "blue";
const rule = css`color: ${color}; font-weight: bold;`;
console.log(rule);

Nested Templates

javascript
const part = "world";
const full = safeHtml`Say ${part} today`;
console.log(full);

Mini Example: i18n Stub

javascript
const dict = { en: { greet: "Hello" }, es: { greet: "Hola" } };
let locale = "en";
 
function i18n(strings, ...values) {
  const key = strings.join("").trim();
  const template = dict[locale][key] ?? key;
  return values.reduce(
    (text, val, i) => text.replace(`{${i}}`, val),
    template
  );
}
 
locale = "es";
console.log(i18n`greet` + " " + "Ada");

FAQ

Tag vs normal template?

Tag adds a function call layer for custom processing.

Can the tag return non-strings?

Yes—React-like libraries return element descriptors or arrays.

String.raw?

Built-in tag preserving backslashes in raw segments—useful for regex paths.

What comes next?

Reflect API.