Tagged template literals take the form of (strings: string[], ...values: any[]): any.
In your example,
let a = (x) => console.log(x);
a`1234`; // prints "Array [ "1234" ]"
x has the type string[], which is an array of all non-interpolated strings (basically anything that's not inside ${}). Because there are no interpolations, the array contains one element (the string "1234"). This is what is passed as the first argument to your function a.
Only template literals can be "tagged" with a function identifier, which is why you've noticed that it doesn't work with single or double-quoted strings, only backticks. I presume it would throw a syntax error if you tried to do it with a regular string, though I haven't tested that.
If you wanted to interpolate a value, you'd do so by receiving the value in the function (which is used as the tag) by adding additional parameters. Note that it is not a single parameter that is an array, but rather separate parameters. You can, of course, create an array from them by using the spread operator (...), as indicated in the function signature above. As in the (modified) example provided by MDN,
const person = 'Mike';
const age = 28;
function tag(strings, person, age) {
const str0 = strings[0]; // "That "
const str1 = strings[1]; // " is a "
// There is technically a string after
// the final expression (in our example),
// but it is empty (""), so disregard.
// const str2 = strings[2];
const age_description = age > 99 ? 'centenarian' : 'youngster';
return [str0, name, str1, ageDescription].join('');
}
const output = tag`That ${person} is a ${age}`;
console.log(output); // "That Mike is a youngster"
Note that as indicated in the comments, there is always a leading and trailing string, even if it happens to be empty. As such, if you began a template literal with an interpolation, strings[0] would be an empty string. In the same manner, ending with an interpolation leaves a trailing empty string, though this isn't as notable (a leading interpolation shifts all indexes by one, a trailing doesn't affect them).
Videos
I see under Template Literals that it's possible to submit a function in front of the literal. Why would you do this, rather than write a function that returns the string you need?
I've come up with two possibilities. One, it might allow you to write things to the DOM in a way similar to React. Second, I saw a YouTube video on declarative programming.
Are tagged template literals used for those purposes? Are there other reasons to use them?
TIA!
You can use tagged templates to build APIs that are more expressive than regular function calls.
For example, I'm working on a proof-of-concept library for SQL queries on JS arrays:
let admins = sql`SELECT name, id FROM ${users}
WHERE ${user => user.roles.indexOf('admin') >= 0}`
Notice it has nothing to do with String interpolation; it uses tagged templates for readability. It would be hard to construct something that reads as intuitively with plain function calls - I guess you'd have something like this:
let admins = sql("SELECT name, id FROM $users WHERE $filter",
{ $users: users, $filter: (user) => user.roles.contains('admin') })
This example is just a fun side project, but I think it shows some of the benefits of tagged templates.
Another example, maybe more obvious, is i18n - a tagged template could insert locale-sensitive versions of your input.
See Sitepoint's explanation:
The final stage of template strings specification is about adding a custom function before the string itself to create a tagged template string.
...
For instance, here is a piece of code to block strings that try to inject custom DOM elements:
var items = []; items.push("banana"); items.push("tomato"); items.push("light saber"); var total = "Trying to hijack your site <BR>"; var myTagFunction = function (strings,...values) { var output = ""; for (var index = 0; index < values.length; index++) { var valueString = values[index].toString(); if (valueString.indexOf(">") !== -1) { // Far more complex tests can be implemented here :) return "String analyzed and refused!"; } output += strings[index] + values[index]; } output += strings[index] return output; } result.innerHTML = myTagFunction `You have ${items.length} item(s) in your basket for a total of $${total}`;Tagged template strings can used for a lot of things like security, localization, creating your own domain specific language, etc.