Better Strings in JavaScript with Template Literals

February 17, 2019

Template literals or string literals is a new JavaScript feature that enhances the ways in which developers can work with strings. It adds functionality for expression interpolation, multi-line strings, nesting templates, and tagged templates. These features make your code more usable and readable. Let’s learn how to use template literals in our JavaScript applications.

A Problem Old as Time

If you’ve done any sort of programming, you’ve almost certainly worked with strings. If you haven’t, I would really love to talk to you. Strings are powerful primitives in many programming languages, including JavaScript. Because strings are such a flexible primitive, they allow you to shoot yourself in the foot quite easily.

JavaScript has traditionally allowed developers to use both single-quotes (') and double-quotes (") to represent string values. Template literals introduce a third way which uses backticks (`). We’ll go into what that means in just a minute, but first let’s take a look at some classic problems developers will likely encounter when working with strings in JavaScript.

// Mismatched case
console.log("My amazing message');
// Uncaught SyntaxError: Invalid or unexpected token
// Does not close the string with double-quotes

console.log('My amazing message");
// Uncaught SyntaxError: Invalid or unexpected token
// Does not close the string with single quotes

// String concatenation
console.log("Back in my day" + "working with strings was a lot harder.");
// "Back in my dayworking with strings was a lot harder."
// Need to add a space before the w, i.e " working..."

// Multi-line 
console.log("I've always wanted to \n write good code");
/*
"I've always wanted to
  write good code"
*/

// Remembering special characters and escape notations
console.log('I've always wanted to write good code');
// Uncaught SyntaxError: missing ) after argument list
// Missing escape character \

I could go on but you get the point. While none of these problems are necessarily hard to fix, they do present a great annoyance to developers. Enter template literals which solve almost all of the nuances of working with strings and more.

Better Strings with Template Literals

To use the new and improved way of working with strings in JavaScript all you have to do is wrap your strings in backticks (`) instead of single or double quotes. Let’s see some examples.

var name = `Ado Kukic`;

console.log(`This doesn't seem all that different`);

All modern browsers support the template literals syntax but if you need legacy browser support there are polyfills as well as transpilers like Babel or Webpack that can help. On the surface, using this new syntax doesn’t seem like it changes the string story too much. Instead of single or double quotes, you’re now just adding a third way of wrapping strings. How is this any better? Just you wait.

Expressions

The biggest feature that template literals add in my opinion is expression interpolation. If you have worked with frameworks like Angular or React, you’ve been using interpolation for your templates and I bet you can’t go back. Let’s see how this works. With the traditional JavaScript string syntax if we wanted to do embed expressions into our strings we would have to do something like this:

var firstName = "Ado";

console.log("Your first name is: " + firstName + ", correct?");

Alternatively, you might have seen string substitution used to make your code a bit more readable like this:

var firstName = "Ado";
var lastName = "Kukic";
var age = 29;

console.log("Your first name is: %s, correct?", firstName);
// "Your first name is: Ado, correct?"

console.log("Your full name is %s %s", firstName, lastName);
// "Your full name is Ado Kukic"

console.log("%s %s, %d", firstName, lastName, age);
// "Ado Kukic, 29"

There are a number of different string substitution options. We saw %s for strings, %d for numbers, but there are others like %j for JSON and %o for object. String substitution helped clean up our code a little bit, but it was not ideal. You had to pass in the variables in the right order, you had to remember the different string substitution patterns, and most importantly this only works in logging to the console.

Template literal expressions gave us a clean way of interoperating the rest of our code with our strings. Let’s see some examples.

// Using double quote string syntax
var firstName = "Ado";

// Using string literal syntax
var lastName = `Kukic`;

// Using string literal syntax
var fullName = `${firstName} ${lastName}`

console.log(fullName);
// "Ado Kukic"

The syntax for expression interpolation is ${}. Anything we place between the curly brackets will be executed as code. In here we can pass variables, functions, or other logic that will be evaluated and it’s final value displayed. Let’s look as some more concrete examples.

var job = "Developer Evangelist";

function fullName(){
  var firstName = "Ado";
  var lastName = "Kukic";

  return `${firstName} ${lastName}`;
}

console.log(`Hi my name is ${fullName()} and I work as a ${job}`);
// "Hi my name is Ado Kukic and I work as a Developer Evangelist"

Express interpolation makes our code much cleaner and easier to read. Finally, we can use expression interpolation in both debugging and throughout our codebase wherever we work with strings.

Multi-line Strings

Multi-line strings in JavaScript without template literals were a pain. If you wanted your string content to be displayed in multiple lines you had to do this:

console.log("Haikus are easy\n" +
"But sometimes they don't make sense\n" +
"Refrigerator");

// Or

console.log("Haikus are easy\nBut sometimes they don't make sense\n Refrigerator");

The use of the \n escape character to start a new line interwoven with the rest of your string made your code really hard to read. If you opted for readability, you had to use the + to concatenate your strings, otherwise if you did everything in one line your code was very difficult to read.

Luckily, the template literal syntax allows us to add multi-line strings with minimal effort. Let’s look at an example.

let haiku = `Haikus are easy
But sometimes they don't make sense
Refrigerator`;

console.log(haiku);
/* 
Haikus are easy
But sometimes they don't make sense
Refrigerator
*/

As you can see, we didn’t need to do anything special here. We declared our string using the template literal syntax and broke up our string into multiple lines within our editor, and when we printed out the string it was printed out in the format we had created in. No need for special characters, but if for whatever reason you wanted to use \n or \t you could and they would behave as expected.

Nesting Templates

You can also nest your template literals inside of each other. A potential use case for this may be wanting to have a more readable way of managing white label configurations in your application for example. The syntax for this is fairly simple, all you do is simply nest your literals within each other - inception style. Let’s see how this works.

let name = `Ado ${`Kukic`}`;

console.log(name);
// "Ado Kukic"

If you’re working with known values already then the above example is overkill. Let’s see a bit more of a concrete example.

let message = `You are a ${`super-${isHero() ? 'hero' : 'villain'`}`}`;
// "You are a super-hero" if isHero() returns true
// "You are a super-villain" if isHero() returns false

While nesting templates are powerful, if you end up using them often I would evaluate your code to see if there are improvements that can be made to not rely on them as much. The nesting code is pretty hard to read and my recommendation would be to avoid nesting templates if possible.

Tagged Templates

Finally, we get to the more advanced uses of template literals with tagged templates. Tagged templates allow you to parse a template literal with a custom function. The tagged template function is written much like any other JavaScript function, with the only requirement being that the first parameter or argument passed in is a strings array. Let’s see an example.

function taggedTemplate(strings, otherArgument){
  // Implementation details
}

You can have as many additional parameters passed into the taggedTemplate as you desire to get the job done and they can be of any type. To use taggedTemplate in our JavaScript code, the syntax is a bit different from a traditional function. Let’s see an example.

var message = taggedTemplate`What the heck is this?`;

Yeah the syntax is a little bit wonky. You call your tagged template function and instead of using parenthesis you just append your string in the template literal format. Since we haven’t added any implementation details to our taggedTemplate function, let’s go back and make some changes to see how this whole tagged template thing works.

function taggedTemplate(strings, otherArgument){
  return `I wonder what this will do`;
}

var message = taggedTemplate`What the heck is this?`;

console.log(message);
// "I wonder what this will do"

As you can see whatever value we return from our taggedTemplate function will be what is logged to our console. In the above example, we sent back a completely different message. While this is possible, I can’t really think of a good use case where you would use it. So let’s what else we can do.

function taggedTemplate(strings, otherArgument){
  var firstWord = strings[0];
  var secondWord = strings[1];

  return `${firstWord} came before ${secondWord}`;
}

var message = taggedTemplate`What the heck is this?`;

console.log(message);
// "What came before the"

Ok, I can see how this might be a bit more useful. But what about that second parameter we’re passing in, the otherArgument. Well at the moment, we’re not passing anything additional into our taggedTemplate function. The way we pass the additional arguments is by passing in template literals in our initial message.

function taggedTemplate(strings, amount){

  if( amount > 100) {
    var message = `Doing great!`;
  } else {
    var message = `Keep at it!`;
  }

  return `Great start! ${message}`;
}

var amount = 500
var message = taggedTemplate`I have ${amount} dollars!`;

console.log(message);
// "Great start! Doing great!"

As you can see when we add expressions to our template literals, they get translated as arguments in our tagged templates. The order here matters so the first expression will be mapped to the first argument after the strings argument, the second to the second, and so on. Tagged templates give us a lot of power and flexibility when it comes to manipulating our strings and formatting them just the way we want. Tagged templates can be a great help when you need to manipulate the DOM from JavaScript in your applications.

Performance Considerations

Template literals are great, make our code a lot more readable, and give us a couple of new features to play with, so there must be a catch somewhere right? Luckily, there is no catch. Using the template literal syntax is just as performant as using the traditional way of working with strings in JavaScript. Since template literals are still a fairly new way of working with strings in JavaScript, performance will likely only improve in the future.

Conclusion

Template literals supercharge the way developers work with strings in JavaScript. The addition of expression interpolation, easy multi-line strings, nested and tagged templates address common issues developers encounter when working with strings and also add new ways of manipulating and working with them. Since all modern browsers support template literals, don’t wait another day to incorporate them into your JavaScript applications.

Newsletter!

Useful articles. Once a month. No spam.