Confusing JavaScript Syntax - Template Literals

One feature sorely missing from JavaScript has been string interpolation and multi-line strings. JavaScript from the beginning has supported strings using either single quotes or double quotes, but there was never mechanism by which variables could be placed inside of the string, and when the string was evaluated those variables would be replaced with their respective values. Additionally, when multi-line strings were needed, an awkward multi-line expression of strings concatenated with addition operators was needed. Both of these limitations made code more difficult to read and maintain.

ES2015 addresses these shortcomings through template literals. Template literals are strings which support interpolation and can span multiple lines. Additionally, template literals support the tag function, which can be used to further process the template and its values.

Variable and Expression Interpolation

Prior to ES2015, when variable values needed to be inserted into strings, they were added through concatenation as shown below.

const fn = 'Bob';  
const ln = 'Smith';

const s = fn + ' ' + ln;

console.log(s);  

With template literals, the code above could be rewritten as follows. Observe use of back ticks to define the template instead of the usual single or double quotes.

const fn = 'Bob';  
const ln = 'Smith';

const s = `${fn} ${ln}`;

console.log(s);

In addition to substituting simple variables, expressions can be used as well.

const fn = 'Bob';  
const ln = 'Smith';

const s = `${fn.toUpperCase()} ${ln.toLowerCase()}`;

console.log(s);

This new syntax simplifies incorporating variable and expression values into strings.

Multi-Line Strings

For the first 20 years of JavaScript, multi-line strings could only be accomplished using the following awkward syntax.

const s = 'JavaScript has been around ' +  
          'for over 20 years. Love it ' +
          'or hate it, JavaScript is ' +
          'taking over the world!';

console.log(s);  

Template literals are particularly useful for component-driven development. For example, Angular 1 and 2 components with embedded template strings greatly benefit from template literals and their multiline capabilities.

Tagged Template Literals

One final benefit of template literals is tag functions. Tag functions permit additional processing of the template literals and supplied values. The tag function can be named anything. In the code below it's named "t" but it could be named any valid JavaScript function name. The first parameter is the parsed template literal with each part stored as an item in an array of parts. The remaining parameters are the values parsed out of the literal. To capture all of the values in an array, a rest operator can be used.

const fn = 'Bob';  
const ln = 'Smith';

function t(parts, ...values) {

  // an array of the parts of the template literal
  console.dir(parts);

  // an array of the values of the expressions
  console.log(values);

  // the tag function can return anything, or
  // return nothing
  // it does not have to an interpolated string
  return 'Some value';
}

t`Hello ${fn} ${ln}!`;

The tag function can process the input and return a string value, but it does not have to return any value at all and the function could perform other kinds of processing on the inputs.

An example of using tagged template literals can be found in Relay applications. Relay uses something called RelayQL, which uses tagged template literals to configure GraphQL queries.

export default class extends Relay.Mutation {

  static fragments = { viewer: () => Relay.QL`fragment on Viewer { id }` }

  // code omitted...

}

Conclusion

As with other new features in ES2015, template literals greatly simplify the common programming tasks of string interpolation and multi-line strings. The tagged function capability is useful by extending simple string generation to perform more powerful operations such as working with GraphQL.