(Disclaimer: I work on the Angular team, but this isn't something the Angular team is considering (yet). This is simply me capturing some thoughts...)
ES2015 added Template Literals to JavaScript (Template Literals is the current term, they were known as "Template Strings" in the first edition)
They're useful for all kinds of things, the most obvious of which is interpolating values in a much more concise way than concatting strings together:
const greeting = `Hello ${name}!`;
//nice with arrow functions
const greet = name => `Hello ${name}!`;
greet('rob'); //Hello rob!
The other, lesser-known API that came along with Template Literals is Tagged Templates.
The idea here is you can "tag" a template literal with a function - effectively allowing you to parse the string and interpolated values yourself:
function format(strings, ...values){
//join the static strings + values ourselves
return strings.reduce((all, part, index) => {
//for each static string, check if there's an interpolated value that follows and join
const name = values[index];
if(!name) return all + part;
return `${all}${part}${name.charAt(0).toUpperCase()}${name.slice(1)}`
}, '');
}
const greet = name => format`Hello ${name}!`
greet('rob') //Hello Rob!
Wrapping my brain around this idea took a while, but the key insight for me was that tagged templates are just a different syntax for invoking your tag function:
const formatted = format`Hello ${'rob'}!`
is just a shorthand for:
const formatted = format(['Hello ', '!'], ['rob']);
(This isn't strictly true, and why that is we'll get into shortly)
Another interesting thing about tagged template literals is that your tag function doesn't necessarily have to return a string. Maybe you want to do something clever with the various parts of the string - you could return the raw parts and values in a data-structure, and wire them up later:
//our tag just captures the strings + values
function localized(strings, ...values){
return [strings, values];
}
function localize(data, locale){
const formatter = new Intl.DateTimeFormat(locale);
const [strings, values] = data;
return strings.reduce((all, str, i) => {
return `${all}${str}${values[i] ? formatter.format(values[i]) : ''}`
}, '');
}
const dateGreeting = date => localized`The current date is ${date}!`;
const currentDate = new Date();
console.log(localize(dateGreeting(currentDate), 'en-US')); //The current date is 6/16/2019!
console.log(localize(dateGreeting(currentDate), 'en-GB')); //The current date is 16/06/2019!