[{"data":1,"prerenderedAt":1148},["ShallowReactive",2],{"blog-\u002Fblog\u002Fjavascript-template-literals-tagged-templates":3},{"id":4,"title":5,"body":6,"description":1133,"difficulty":1134,"extension":1135,"framework":1136,"frameworkSlug":1137,"meta":1138,"navigation":115,"order":112,"path":1139,"qaPath":1140,"seo":1141,"stem":1142,"subtopic":1143,"topic":1144,"topicSlug":1145,"updated":1146,"__hash__":1147},"blog\u002Fblog\u002Fjavascript-template-literals-tagged-templates.md","JavaScript Template Literals & Tagged Templates — Interpolation, Multiline and DSLs",{"type":7,"value":8,"toc":1120},"minimark",[9,14,32,36,45,140,151,236,254,258,264,315,329,333,355,432,439,443,458,529,542,546,559,605,618,622,625,711,714,718,725,774,792,910,914,931,985,989,996,1055,1059,1113,1116],[10,11,13],"h2",{"id":12},"strings-upgraded","Strings, upgraded",[15,16,17,18,22,23,27,28,31],"p",{},"Before ES2015, building strings in JavaScript meant clumsy concatenation with ",[19,20,21],"code",{},"+"," and escaped\nnewlines. ",[24,25,26],"strong",{},"Template literals"," — strings written with backticks — replaced that with clean\ninterpolation, real multiline support, and a powerful extension called ",[24,29,30],{},"tagged templates","\nthat turns a string into a mini domain-specific language. They're used everywhere: logging,\nHTML generation, CSS-in-JS, GraphQL queries, and internationalization. This guide covers the\neveryday features and the advanced tagging mechanism, including the security pitfalls to\nrespect.",[10,33,35],{"id":34},"interpolation-and-multiline","Interpolation and multiline",[15,37,38,39,44],{},"A template literal uses backticks and embeds expressions with ",[24,40,41],{},[19,42,43],{},"${ }",". Newlines inside the\nbackticks are preserved literally.",[46,47,52],"pre",{"className":48,"code":49,"language":50,"meta":51,"style":51},"language-js shiki shiki-themes github-light github-dark","const name = 'Ada', count = 3\nconst msg = `Hello, ${name}! You have ${count} messages.`\n\nconst block = `Line one\nLine two`        \u002F\u002F real newline, no \\n needed\n","js","",[19,53,54,86,110,117,130],{"__ignoreMap":51},[55,56,59,63,67,70,74,78,81,83],"span",{"class":57,"line":58},"line",1,[55,60,62],{"class":61},"szBVR","const",[55,64,66],{"class":65},"sj4cs"," name",[55,68,69],{"class":61}," =",[55,71,73],{"class":72},"sZZnC"," 'Ada'",[55,75,77],{"class":76},"sVt8B",", ",[55,79,80],{"class":65},"count",[55,82,69],{"class":61},[55,84,85],{"class":65}," 3\n",[55,87,89,91,94,96,99,102,105,107],{"class":57,"line":88},2,[55,90,62],{"class":61},[55,92,93],{"class":65}," msg",[55,95,69],{"class":61},[55,97,98],{"class":72}," `Hello, ${",[55,100,101],{"class":76},"name",[55,103,104],{"class":72},"}! You have ${",[55,106,80],{"class":76},[55,108,109],{"class":72},"} messages.`\n",[55,111,113],{"class":57,"line":112},3,[55,114,116],{"emptyLinePlaceholder":115},true,"\n",[55,118,120,122,125,127],{"class":57,"line":119},4,[55,121,62],{"class":61},[55,123,124],{"class":65}," block",[55,126,69],{"class":61},[55,128,129],{"class":72}," `Line one\n",[55,131,133,136],{"class":57,"line":132},5,[55,134,135],{"class":72},"Line two`",[55,137,139],{"class":138},"sJ8bj","        \u002F\u002F real newline, no \\n needed\n",[15,141,142,143,146,147,150],{},"Anything inside ",[19,144,145],{},"${}"," is a full ",[24,148,149],{},"expression"," — arithmetic, function calls, ternaries, even\nnested template literals — evaluated and coerced to a string.",[46,152,154],{"className":48,"code":153,"language":50,"meta":51,"style":51},"`Total: ${items.reduce((s, i) => s + i.price, 0)}`\n`Status: ${active ? 'on' : 'off'}`   \u002F\u002F ternary in a slot\n",[19,155,156,213],{"__ignoreMap":51},[55,157,158,161,164,167,171,174,177,179,182,185,188,191,194,197,199,202,204,207,210],{"class":57,"line":58},[55,159,160],{"class":72},"`Total: ${",[55,162,163],{"class":76},"items",[55,165,166],{"class":72},".",[55,168,170],{"class":169},"sScJk","reduce",[55,172,173],{"class":72},"((",[55,175,176],{"class":65},"s",[55,178,77],{"class":72},[55,180,181],{"class":65},"i",[55,183,184],{"class":72},") ",[55,186,187],{"class":61},"=>",[55,189,190],{"class":76}," s",[55,192,193],{"class":61}," +",[55,195,196],{"class":76}," i",[55,198,166],{"class":72},[55,200,201],{"class":76},"price",[55,203,77],{"class":72},[55,205,206],{"class":65},"0",[55,208,209],{"class":72},")",[55,211,212],{"class":72},"}`\n",[55,214,215,218,221,224,227,230,233],{"class":57,"line":88},[55,216,217],{"class":72},"`Status: ${",[55,219,220],{"class":76},"active",[55,222,223],{"class":61}," ?",[55,225,226],{"class":72}," 'on'",[55,228,229],{"class":61}," :",[55,231,232],{"class":72}," 'off'}`",[55,234,235],{"class":138},"   \u002F\u002F ternary in a slot\n",[15,237,238,239,241,242,245,246,249,250,253],{},"Note: ",[19,240,145],{}," holds an ",[243,244,149],"em",{},", not a statement — you can't put ",[19,247,248],{},"if","\u002F",[19,251,252],{},"for"," there. For\nconditional content, use a ternary or compute the fragment into a variable first.",[10,255,257],{"id":256},"why-prefer-them-over-concatenation","Why prefer them over concatenation",[15,259,260,261,263],{},"Template literals are more readable and less error-prone than ",[19,262,21],{}," concatenation, which is noisy\nand prone to stray-space and coercion bugs.",[46,265,267],{"className":48,"code":266,"language":50,"meta":51,"style":51},"'Hi ' + name + ', you have ' + count + ' items'   \u002F\u002F noisy, easy to mis-space\n`Hi ${name}, you have ${count} items`             \u002F\u002F clear\n",[19,268,269,297],{"__ignoreMap":51},[55,270,271,274,276,279,281,284,286,289,291,294],{"class":57,"line":58},[55,272,273],{"class":72},"'Hi '",[55,275,193],{"class":61},[55,277,278],{"class":76}," name ",[55,280,21],{"class":61},[55,282,283],{"class":72}," ', you have '",[55,285,193],{"class":61},[55,287,288],{"class":76}," count ",[55,290,21],{"class":61},[55,292,293],{"class":72}," ' items'",[55,295,296],{"class":138},"   \u002F\u002F noisy, easy to mis-space\n",[55,298,299,302,304,307,309,312],{"class":57,"line":88},[55,300,301],{"class":72},"`Hi ${",[55,303,101],{"class":76},[55,305,306],{"class":72},"}, you have ${",[55,308,80],{"class":76},[55,310,311],{"class":72},"} items`",[55,313,314],{"class":138},"             \u002F\u002F clear\n",[15,316,317,318,320,321,324,325,328],{},"They also make intent explicit: each slot is obviously a value being inserted, whereas ",[19,319,21],{}," can\nsilently produce ",[19,322,323],{},"NaN"," or ",[19,326,327],{},"'[object Object]'"," with the wrong operand.",[10,330,332],{"id":331},"coercion-inside-slots","Coercion inside slots",[15,334,335,336,338,339,342,343,346,347,350,351,354],{},"Each ",[19,337,145],{}," result is converted to a string via the standard rules: objects call ",[19,340,341],{},"toString()","\n(usually yielding the unhelpful ",[19,344,345],{},"[object Object]","), arrays join with commas, and ",[19,348,349],{},"null","\u002F\n",[19,352,353],{},"undefined"," stringify literally.",[46,356,358],{"className":48,"code":357,"language":50,"meta":51,"style":51},"`${[1, 2, 3]}`       \u002F\u002F '1,2,3'\n`${ {a: 1} }`        \u002F\u002F '[object Object]' rarely useful\n`${JSON.stringify({a: 1})}`   \u002F\u002F '{\"a\":1}' usually what you want for objects\n",[19,359,360,390,407],{"__ignoreMap":51},[55,361,362,365,368,371,373,376,378,381,384,387],{"class":57,"line":58},[55,363,364],{"class":72},"`${",[55,366,367],{"class":72},"[",[55,369,370],{"class":65},"1",[55,372,77],{"class":72},[55,374,375],{"class":65},"2",[55,377,77],{"class":72},[55,379,380],{"class":65},"3",[55,382,383],{"class":72},"]",[55,385,386],{"class":72},"}`",[55,388,389],{"class":138},"       \u002F\u002F '1,2,3'\n",[55,391,392,394,397,399,402,404],{"class":57,"line":88},[55,393,364],{"class":72},[55,395,396],{"class":72}," {a: ",[55,398,370],{"class":65},[55,400,401],{"class":72},"} ",[55,403,386],{"class":72},[55,405,406],{"class":138},"        \u002F\u002F '[object Object]' rarely useful\n",[55,408,409,411,414,416,419,422,424,427,429],{"class":57,"line":112},[55,410,364],{"class":72},[55,412,413],{"class":65},"JSON",[55,415,166],{"class":72},[55,417,418],{"class":169},"stringify",[55,420,421],{"class":72},"({a: ",[55,423,370],{"class":65},[55,425,426],{"class":72},"})",[55,428,386],{"class":72},[55,430,431],{"class":138},"   \u002F\u002F '{\"a\":1}' usually what you want for objects\n",[15,433,434,435,438],{},"For objects you almost always want ",[19,436,437],{},"JSON.stringify"," rather than the default object coercion.",[10,440,442],{"id":441},"tagged-templates","Tagged templates",[15,444,445,446,449,450,453,454,457],{},"A ",[24,447,448],{},"tagged template"," prefixes a template literal with a function. That function receives the\n",[24,451,452],{},"array of string segments"," as its first argument and each interpolated ",[24,455,456],{},"value"," as\nsubsequent arguments — giving you full control over the output.",[46,459,461],{"className":48,"code":460,"language":50,"meta":51,"style":51},"function tag(strings, ...values) {\n  return { strings, values }\n}\ntag`Hi ${name}, you are ${count}`\n\u002F\u002F strings: ['Hi ', ', you are ', '']  \u003C- always one more than values\n\u002F\u002F values:  [name, count]\n",[19,462,463,489,497,502,518,523],{"__ignoreMap":51},[55,464,465,468,471,474,478,480,483,486],{"class":57,"line":58},[55,466,467],{"class":61},"function",[55,469,470],{"class":169}," tag",[55,472,473],{"class":76},"(",[55,475,477],{"class":476},"s4XuR","strings",[55,479,77],{"class":76},[55,481,482],{"class":61},"...",[55,484,485],{"class":476},"values",[55,487,488],{"class":76},") {\n",[55,490,491,494],{"class":57,"line":88},[55,492,493],{"class":61},"  return",[55,495,496],{"class":76}," { strings, values }\n",[55,498,499],{"class":57,"line":112},[55,500,501],{"class":76},"}\n",[55,503,504,507,509,511,514,516],{"class":57,"line":119},[55,505,506],{"class":169},"tag",[55,508,301],{"class":72},[55,510,101],{"class":76},[55,512,513],{"class":72},"}, you are ${",[55,515,80],{"class":76},[55,517,212],{"class":72},[55,519,520],{"class":57,"line":132},[55,521,522],{"class":138},"\u002F\u002F strings: ['Hi ', ', you are ', '']  \u003C- always one more than values\n",[55,524,526],{"class":57,"line":525},6,[55,527,528],{"class":138},"\u002F\u002F values:  [name, count]\n",[15,530,531,532,534,535,538,539,541],{},"The ",[19,533,477],{}," array always has ",[24,536,537],{},"one more"," element than ",[19,540,485],{},", because the segments\nsurround the interpolations. Tag functions zip them together — and crucially, the tag doesn't\nhave to return a string at all.",[10,543,545],{"id":544},"stringraw-and-raw-strings","String.raw and raw strings",[15,547,548,549,554,555,558],{},"The built-in ",[24,550,551],{},[19,552,553],{},"String.raw"," tag returns the string with escape sequences ",[24,556,557],{},"uninterpreted"," —\nbackslashes stay literal. This is invaluable for Windows paths, regex source, and LaTeX.",[46,560,562],{"className":48,"code":561,"language":50,"meta":51,"style":51},"String.raw`C:\\new\\test`   \u002F\u002F 'C:\\\\new\\\\test' — backslashes preserved\n`C:\\new\\test`             \u002F\u002F 'C:' + newline + 'ew' + tab + 'est'\n",[19,563,564,590],{"__ignoreMap":51},[55,565,566,569,572,575,578,581,584,587],{"class":57,"line":58},[55,567,568],{"class":76},"String.",[55,570,571],{"class":169},"raw",[55,573,574],{"class":72},"`C:",[55,576,577],{"class":65},"\\n",[55,579,580],{"class":72},"ew",[55,582,583],{"class":65},"\\t",[55,585,586],{"class":72},"est`",[55,588,589],{"class":138},"   \u002F\u002F 'C:\\\\new\\\\test' — backslashes preserved\n",[55,591,592,594,596,598,600,602],{"class":57,"line":88},[55,593,574],{"class":72},[55,595,577],{"class":65},[55,597,580],{"class":72},[55,599,583],{"class":65},[55,601,586],{"class":72},[55,603,604],{"class":138},"             \u002F\u002F 'C:' + newline + 'ew' + tab + 'est'\n",[15,606,607,608,611,612,614,615,617],{},"Inside any tag, ",[19,609,610],{},"strings.raw"," holds the un-escaped segments, so custom tags can choose cooked or\nraw text. ",[19,613,553],{}," is literally implemented by joining ",[19,616,610],{}," with the values.",[10,619,621],{"id":620},"real-world-tagged-templates","Real-world tagged templates",[15,623,624],{},"Tagged templates power several popular libraries by parsing the literal at the call site:",[46,626,628],{"className":48,"code":627,"language":50,"meta":51,"style":51},"\u002F\u002F styled-components — CSS-in-JS\nconst Button = styled.button`\n  color: ${props => props.primary ? 'white' : 'black'};\n`\n\n\u002F\u002F graphql-tag — parses the query into an AST\nconst QUERY = gql`query { user { id name } }`\n",[19,629,630,635,653,682,686,690,695],{"__ignoreMap":51},[55,631,632],{"class":57,"line":58},[55,633,634],{"class":138},"\u002F\u002F styled-components — CSS-in-JS\n",[55,636,637,639,642,644,647,650],{"class":57,"line":88},[55,638,62],{"class":61},[55,640,641],{"class":65}," Button",[55,643,69],{"class":61},[55,645,646],{"class":76}," styled.",[55,648,649],{"class":169},"button",[55,651,652],{"class":72},"`\n",[55,654,655,658,661,664,667,669,672,674,677,679],{"class":57,"line":112},[55,656,657],{"class":72},"  color: ${",[55,659,660],{"class":65},"props",[55,662,663],{"class":61}," =>",[55,665,666],{"class":76}," props",[55,668,166],{"class":72},[55,670,671],{"class":76},"primary",[55,673,223],{"class":61},[55,675,676],{"class":72}," 'white'",[55,678,229],{"class":61},[55,680,681],{"class":72}," 'black'};\n",[55,683,684],{"class":57,"line":119},[55,685,652],{"class":72},[55,687,688],{"class":57,"line":132},[55,689,116],{"emptyLinePlaceholder":115},[55,691,692],{"class":57,"line":525},[55,693,694],{"class":138},"\u002F\u002F graphql-tag — parses the query into an AST\n",[55,696,698,700,703,705,708],{"class":57,"line":697},7,[55,699,62],{"class":61},[55,701,702],{"class":65}," QUERY",[55,704,69],{"class":61},[55,706,707],{"class":169}," gql",[55,709,710],{"class":72},"`query { user { id name } }`\n",[15,712,713],{},"The tag receives the static chunks plus the dynamic interpolations and builds something\ndomain-specific — a styled component, a parsed query, a translated message. This \"embedded DSL\"\ncapability is the deepest use of template literals.",[10,715,717],{"id":716},"the-security-pitfall","The security pitfall",[15,719,720,721,724],{},"Plain template literals perform ",[24,722,723],{},"no escaping"," — interpolated values go in verbatim. Building\nHTML or SQL by interpolation invites XSS and SQL injection.",[46,726,728],{"className":48,"code":727,"language":50,"meta":51,"style":51},"el.innerHTML = `\u003Cdiv>${userInput}\u003C\u002Fdiv>`            \u002F\u002F XSS if userInput has \u003Cscript>\ndb.query(`SELECT * FROM users WHERE id = ${id}`)    \u002F\u002F SQL injection\n",[19,729,730,750],{"__ignoreMap":51},[55,731,732,735,738,741,744,747],{"class":57,"line":58},[55,733,734],{"class":76},"el.innerHTML ",[55,736,737],{"class":61},"=",[55,739,740],{"class":72}," `\u003Cdiv>${",[55,742,743],{"class":76},"userInput",[55,745,746],{"class":72},"}\u003C\u002Fdiv>`",[55,748,749],{"class":138},"            \u002F\u002F XSS if userInput has \u003Cscript>\n",[55,751,752,755,758,760,763,766,768,771],{"class":57,"line":88},[55,753,754],{"class":76},"db.",[55,756,757],{"class":169},"query",[55,759,473],{"class":76},[55,761,762],{"class":72},"`SELECT * FROM users WHERE id = ${",[55,764,765],{"class":76},"id",[55,767,386],{"class":72},[55,769,770],{"class":76},")    ",[55,772,773],{"class":138},"\u002F\u002F SQL injection\n",[15,775,776,777,780,781,783,784,787,788,791],{},"For HTML, use a ",[24,778,779],{},"sanitizing tag"," that escapes the ",[243,782,485],{}," while trusting the static\n",[243,785,786],{},"segments","; for SQL, use ",[24,789,790],{},"parameterized queries",". Never interpolate untrusted data directly\ninto markup or queries.",[46,793,795],{"className":48,"code":794,"language":50,"meta":51,"style":51},"function safeHtml(strings, ...values) {\n  return strings.reduce((out, s, i) =>\n    out + s + (i \u003C values.length ? escapeHtml(values[i]) : ''), '')\n}\nsafeHtml`\u003Cp>${userInput}\u003C\u002Fp>`   \u002F\u002F userInput is escaped\n",[19,796,797,816,843,890,894],{"__ignoreMap":51},[55,798,799,801,804,806,808,810,812,814],{"class":57,"line":58},[55,800,467],{"class":61},[55,802,803],{"class":169}," safeHtml",[55,805,473],{"class":76},[55,807,477],{"class":476},[55,809,77],{"class":76},[55,811,482],{"class":61},[55,813,485],{"class":476},[55,815,488],{"class":76},[55,817,818,820,823,825,827,830,832,834,836,838,840],{"class":57,"line":88},[55,819,493],{"class":61},[55,821,822],{"class":76}," strings.",[55,824,170],{"class":169},[55,826,173],{"class":76},[55,828,829],{"class":476},"out",[55,831,77],{"class":76},[55,833,176],{"class":476},[55,835,77],{"class":76},[55,837,181],{"class":476},[55,839,184],{"class":76},[55,841,842],{"class":61},"=>\n",[55,844,845,848,850,853,855,858,861,864,867,869,872,875,878,881,884,887],{"class":57,"line":112},[55,846,847],{"class":76},"    out ",[55,849,21],{"class":61},[55,851,852],{"class":76}," s ",[55,854,21],{"class":61},[55,856,857],{"class":76}," (i ",[55,859,860],{"class":61},"\u003C",[55,862,863],{"class":76}," values.",[55,865,866],{"class":65},"length",[55,868,223],{"class":61},[55,870,871],{"class":169}," escapeHtml",[55,873,874],{"class":76},"(values[i]) ",[55,876,877],{"class":61},":",[55,879,880],{"class":72}," ''",[55,882,883],{"class":76},"), ",[55,885,886],{"class":72},"''",[55,888,889],{"class":76},")\n",[55,891,892],{"class":57,"line":119},[55,893,501],{"class":76},[55,895,896,899,902,904,907],{"class":57,"line":132},[55,897,898],{"class":169},"safeHtml",[55,900,901],{"class":72},"`\u003Cp>${",[55,903,743],{"class":76},[55,905,906],{"class":72},"}\u003C\u002Fp>`",[55,908,909],{"class":138},"   \u002F\u002F userInput is escaped\n",[10,911,913],{"id":912},"caching-the-strings-array-is-stable","Caching: the strings array is stable",[15,915,916,917,920,921,927,928,930],{},"A useful performance detail: for a given tagged-template ",[24,918,919],{},"call site",", the engine reuses the\n",[24,922,923,924,926],{},"same frozen ",[19,925,477],{}," array"," across invocations. Libraries exploit this to memoize parsed\nresults (compiled CSS, GraphQL ASTs) keyed on the ",[19,929,477],{}," object identity.",[46,932,934],{"className":48,"code":933,"language":50,"meta":51,"style":51},"function tag(strings) { \u002F* same `strings` reference every call *\u002F }\nfunction render() { return tag`hello ${x}` }\n\u002F\u002F render() called repeatedly receives the identical strings array\n",[19,935,936,955,980],{"__ignoreMap":51},[55,937,938,940,942,944,946,949,952],{"class":57,"line":58},[55,939,467],{"class":61},[55,941,470],{"class":169},[55,943,473],{"class":76},[55,945,477],{"class":476},[55,947,948],{"class":76},") { ",[55,950,951],{"class":138},"\u002F* same `strings` reference every call *\u002F",[55,953,954],{"class":76}," }\n",[55,956,957,959,962,965,968,970,973,976,978],{"class":57,"line":88},[55,958,467],{"class":61},[55,960,961],{"class":169}," render",[55,963,964],{"class":76},"() { ",[55,966,967],{"class":61},"return",[55,969,470],{"class":169},[55,971,972],{"class":72},"`hello ${",[55,974,975],{"class":76},"x",[55,977,386],{"class":72},[55,979,954],{"class":76},[55,981,982],{"class":57,"line":112},[55,983,984],{"class":138},"\u002F\u002F render() called repeatedly receives the identical strings array\n",[10,986,988],{"id":987},"handling-indentation-and-lists","Handling indentation and lists",[15,990,991,992,995],{},"Two practical gotchas. Multiline literals preserve source indentation, so nested code leaks\nleading spaces — strip with a dedent helper or regex. And rendering a list needs an explicit\n",[19,993,994],{},"join",", since default array coercion inserts commas.",[46,997,999],{"className":48,"code":998,"language":50,"meta":51,"style":51},"`\u003Cul>${items.map(i => `\u003Cli>${i}\u003C\u002Fli>`).join('')}\u003C\u002Ful>`   \u002F\u002F controlled separator\n`\u003Cul>${items}\u003C\u002Ful>`   \u002F\u002F inserts commas between items\n",[19,1000,1001,1044],{"__ignoreMap":51},[55,1002,1003,1006,1008,1010,1013,1015,1017,1019,1022,1024,1027,1030,1032,1034,1036,1038,1041],{"class":57,"line":58},[55,1004,1005],{"class":72},"`\u003Cul>${",[55,1007,163],{"class":76},[55,1009,166],{"class":72},[55,1011,1012],{"class":169},"map",[55,1014,473],{"class":72},[55,1016,181],{"class":65},[55,1018,663],{"class":61},[55,1020,1021],{"class":72}," `\u003Cli>${",[55,1023,181],{"class":76},[55,1025,1026],{"class":72},"}\u003C\u002Fli>`",[55,1028,1029],{"class":72},").",[55,1031,994],{"class":169},[55,1033,473],{"class":72},[55,1035,886],{"class":72},[55,1037,209],{"class":72},[55,1039,1040],{"class":72},"}\u003C\u002Ful>`",[55,1042,1043],{"class":138},"   \u002F\u002F controlled separator\n",[55,1045,1046,1048,1050,1052],{"class":57,"line":88},[55,1047,1005],{"class":72},[55,1049,163],{"class":76},[55,1051,1040],{"class":72},[55,1053,1054],{"class":138},"   \u002F\u002F inserts commas between items\n",[10,1056,1058],{"id":1057},"key-takeaways","Key takeaways",[1060,1061,1062,1073,1082,1093,1101,1107],"ul",{},[1063,1064,1065,1066,1069,1070,1072],"li",{},"Template literals use backticks with ",[19,1067,1068],{},"${expression}"," interpolation and preserve real\nnewlines — cleaner than ",[19,1071,21],{}," concatenation.",[1063,1074,1075,1076,1078,1079,1081],{},"Slots hold expressions (not statements); objects coerce to ",[19,1077,345],{},", so use\n",[19,1080,437],{}," when needed.",[1063,1083,1084,1086,1087,1089,1090,1092],{},[24,1085,442],{}," call a function with the ",[19,1088,477],{}," array (one longer than ",[19,1091,485],{},") plus\nthe interpolated values, enabling DSLs and full output control.",[1063,1094,1095,1097,1098,1100],{},[19,1096,553],{}," (and ",[19,1099,610],{},") gives un-escaped text — ideal for paths and regex.",[1063,1102,1103,1104,1106],{},"Plain interpolation does ",[24,1105,723],{}," — use sanitizing tags for HTML and parameterized\nqueries for SQL to prevent injection.",[1063,1108,1109,1110,1112],{},"The per-call-site ",[19,1111,477],{}," array is stable, enabling caching in libraries.",[15,1114,1115],{},"Template literals turn string building from a chore into a feature — and tagged templates extend\nthat into embedded mini-languages, as long as you handle untrusted input safely.",[1117,1118,1119],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":51,"searchDepth":88,"depth":88,"links":1121},[1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132],{"id":12,"depth":88,"text":13},{"id":34,"depth":88,"text":35},{"id":256,"depth":88,"text":257},{"id":331,"depth":88,"text":332},{"id":441,"depth":88,"text":442},{"id":544,"depth":88,"text":545},{"id":620,"depth":88,"text":621},{"id":716,"depth":88,"text":717},{"id":912,"depth":88,"text":913},{"id":987,"depth":88,"text":988},{"id":1057,"depth":88,"text":1058},"Master JavaScript template literals — interpolation, multiline strings, expression embedding, tagged templates, String.raw, and the security pitfalls of unescaped interpolation.","medium","md","JavaScript","javascript",{},"\u002Fblog\u002Fjavascript-template-literals-tagged-templates","\u002Fjavascript\u002Fmodern\u002Ftemplate-literals",{"title":5,"description":1133},"blog\u002Fjavascript-template-literals-tagged-templates","Template Literals & Tagged Templates","Modern JavaScript (ES6+)","modern","2026-06-18","jSP30RqmD3XlAx3r0lo6SC-GPu3JTVMqnUHcNCP1ENA",1781808673080]