ponyfoo.com

Template Literals are Strictly Better Strings

The majority of the community has implicitly agreed on using const as the default over var. The const statement makes your code more clear, by describing a read-only value at declaration time. It also makes it clear that the variable isn’t meant to be used before its declaration, avoiding silly mistakes that could occur when using var. For these reasons, const also improves interaction with static analysis tools such as eslint.

This article explores how template literals are strictly better than strings, and how they too should become the new default of a post-ES6 era – over single and double quoted strings.

Improve this article
Nicolás Bevacqua
| 14 minute read | 34

Strictly better is a term I picked up from my tenure as a Magic* player. According to the definition, a Magic card is said to be strictly better than another when it’s better in some way but isn’t worse in any way.

Strictly better describes a card which is, in isolation from other effects, superior to another card in at least one respect, while being worse in zero respects.

* a fantasy trading card game, it’s kind of like a mix between chess and poker. Yeah.

When I say that template literals are strictly better than single and double quoted strings, I mean that they are superior in several respects while not being worse in any aspects. As noted in the definition, there’s always some situations in which a “strictly better” card could in fact be worse than the other, but these situations are atypical enough that we can get away with using the “strictly better” terminology on a figurative basis.

So how exactly are template literals strictly better than single and double quoted strings? And why haven’t they pervasively taken over single and double quoted strings, if that were the case?

Read on and find out.

Expression Interpolation

Assuming an ES6 codebase, there are several ways to do interpolation in strings.

You could use string concatenation, involving + signs and a string for each piece of the template you’re working on. Using concatenation can quickly get out of hand when dealing with longer templates, not to mention reusability is hard unless you abstract away your template in a small function.

'Hello ' + name + '! It\'s a pleasure to greet you.'

You could use util.format in Node. Here we have placeholders such as %s which describes how the value is to be formatted, but doesn’t say anything about the value that should be placed in that socket in the template. This method – and similar ones – scales better than string concatenation, but it can be difficult to infer the context for each replacement value in the template without a small function that matches its arguments to each value for the template.

util.format('Hello %s! It\'s a pleasure to greet you.', name)

You could use string interpolation in template literals. Here you can inline JavaScript expressions such as expression wrapped in ${expression}. It’s nice to have a name for the slot, such as the name for the person you’re greeting, placed directly within the template.

`Hello ${name}! It's a pleasure to greet you.`

Of course, nothing is stopping you from using template literals in the previous two incarnations of interpolation. Overlooking the fact that we should probably be just using expression interpolation within a single template literal, nothing stops us from using template literals in the exact same way as we used quoted strings.

`Hello ` + name + `! It's a pleasure to greet you.`
util.format(`Hello %s! It's a pleasure to greet you.`, name)

Template literals give us the choice to interpolate inline in the string, if we want to, while quoted strings don’t. As an added bonus, interpolation could be several levels deep: any expressions – including other template literals – can be used for interpolations.

Character Escaping

This one is fairly minor, but it’s still worth pointing out.

In single quoted strings, we need to escape single quotes using \'.

'What\'s that?'

In double quoted strings, we need to escape double quotes using \".

"Hey, who's \"that\" are you referring to?"

In template literals, we need to escape backticks using \`.

`Hey, programmers use backticks to render code, like \`this\`.`

You’re far less likely to need backticks in your everyday strings than single or double quotes, which are commonplace in English and language in general. Using template literals, then, translates into less escape codes that can pollute your otherwise beautiful strings.

Multiline Strings

Making regular strings multiline can be annoying. We have a variety of options, though, for both single and double quoted strings.

Using an array and then concatenating with \n is possibly my favorite approach. Here we need individual strings per line, and the surrounding array with its join, but there’s no escaping involved.

[
  '# Ingredients',
  '',
  '- 2x Tomato',
  '- 2x Lemon',
  '- 300cc Vodka',
  '- Pepper'
].join('\n')

An almost identical approach, that seems more typically favored by JavaScript developers, is to concatenate using +. In this case we’d have to add our \n ourselves. Typically, however, developers do not mind the lack of new lines because their multiline string is used to declare a piece of HTML for Angular and jQuery applications. Using + is a bit noisier than using ,, and we’d have to hand-roll our \n, but it does allow for us to use a single string. Even though inline HTML is far from ideal, avoiding new lines is hardly a problem on top of that.

'<div>' +
  '<span>Hello </span>' +
  '<span>' +
  name +
  '</span>' +
'</div>'

An approach you hardly ever see is using \n new line escapes followed by an escape \ that allows you to continue writing the same string on a new line. This is noisy on the right hand side, but not as noisy on the left hand side, but it does allow for us to use a single string.

'# Ingredients\n\
\n\
- 2x Tomato\n\
- 2x Lemon\n\
- 300cc Vodka\n\
- Pepper'

Plus, if you don’t need the \n escapes, – as is the case with HTML strings – you can end up with quite decent looking strings.

'<div>\
  <span>Hello </span>\
  <span>' +
  name +
  '</span>\
</div>'

Wait, that didn’t look so great. That’s because as soon as we have some sort of interpolation in the string, we’re back to concatenating, and it can get awful.

Then there’s other less frequently surfaced approaches, such as using a comment in a function and a library to extract the comment into a multiline string. Here’s an example using Sindre’s multiline package. This approach only has noise on the beginning and end of the declaration, but not within, which is why it can be preferred. It does involve a third party package and a convoluted hack just to render multiline strings, which some people could take issue with.

multiline(function(){/*
<!doctype html>
<html>
  <body>
    <h1>Pony Foo</h1>
  </body>
</html>
*/});

When it comes to template literals, multiline support is included by default. The following example, using template literals, is equivalent to the previous one where we used multiline.

`<!doctype html>
<html>
  <body>
    <h1>Pony Foo</h1>
  </body>
</html>`

If you have expressions you need to interpolate into your multiline strings, template literals aren’t shaken up like other approaches.

`<!doctype html>
<html>
  <body>
    <h1>${title}</h1>
  </body>
</html>`

Plus, if you’re worried about XSS and you’d like to HTML-encode interpolations, you could use tagged templates that automatically do this for you. The following example uses an encode tagged template to escape interpolations in an HTML string using a brittle escape implementation.

function encode (template, ...expressions) {
  const escape = text => text
    .replace(/&/g, `&amp;`)
    .replace(/"/g, `&quot;`)
    .replace(/'/g, `&#39;`)
    .replace(/</g, `&lt;`)
    .replace(/>/g, `&gt;`)

  return template.reduce((result, part, i) => {
    return result + escape(expressions[i - 1]) + part)
  })
}

const title = `<script src='https://malicio.us/js'></script>`

encode`<!doctype html>
<html>
  <body>
    <h1>${title}</h1>
  </body>
</html>`

The resulting string is plain HTML, where interpolated expressions have been HTML encoded.

<!doctype html>
<html>
  <body>
    <h1>&lt;script src=&#39;https://malicio.us/js&#39;&gt;&lt;/script&gt;</h1>
  </body>
</html>

Again, you have the option of doing all of this, but nothing impedes you from applying any of the previous approaches to template literals.

But, JSON.

The JSON argument is bound to come up, but we can shrug it off as a weak one. In JSON, strings – and even property keys – must be double quoted.

{
  "key": "value"
}

You can’t use single quotes to declare strings in JSON, yet they are typically favored over double quotes when it comes to JavaScript code. The same argument can, by transitive property, be applied to template literals: you can’t use template literals to declare strings in JSON, yet they should be favored over single or double quotes.

Choose Your Weapon

Here’s a Twitter poll I ran last week, asking about whether people are using template literals as their default string representation of choice.

Half of respondents still use single quotes, where close to half claim to be prefer template literals. Some replied to my tweet saying that they use template literals when they explicitly need interpolation or multiline support, but otherwise fall back to single quoted strings.

Using backticks is better because you rarely need to escape backticks \`, you get multiline support, and you get variable interpolation. Many admitted they’d switch over from single quoted strings to template literals when interpolation or multiline support was required, so why not switch everything over by default and take advantage of the lower amount of \` escapes as opposed to \'?

The only valid argument I’ve read against using template literals, much like with const, is that people are used to single quoted strings. While familiarity is a fair claim, you can conjure up the habit of using template literals very quickly, as we’ll explore next.

Using eslint: the quotes Rule

ESLint is a modern linter for JavaScript code bases. If you’re still on another linter, I strongly encourage you to check it out.

The "quotes" rule tells ESLint that string literals must be declared using backticks, or template literals, and that otherwise an error should be reported. This way we can ensure that, going forward, we’re using template literals across our codebase.

"quotes": ["error", "backtick"]

“But, Nico” – you may object – “a rule like this would report hundreds of stylistic errors in my code base, and I have no time to fix all of that.”. You’d be absolutely right.

ESLint ships with a --fix flag for its CLI, where it’ll attempt to resolve stylistic issues, before reporting them as hard errors. If an stylistic issue can be fixed, then --fix will take care of it for you without ever complaining about it. As it turns out, the quotes rule is an stylistic choice that is easily fixed with --fix.

The following command would turn all your strings into template literals, provided you’ve set up the quotes rule to "backtick".

eslint --fix .

Ta-da! 🎉

You may find your code base now has bits like the following, instead of the single quoted strings you previously had.

`Hello ` + name + `!`

You can gradually upgrade code like the above into interpolated expressions over time, getting to a more consistent code base. There’s no excuse, however, to get away with not using template literals!

Quick Disclaimer: 'use strict' Directives

Note the 'use strict' directive won’t be executed if wrapped in backticks instead of single or double quotes. While eslint --fix doesn’t break 'use strict' statements, you could mistakenly do that by hand, so please avoid doing so! 😨

Now go evangelize the use of template literals everywhere, so that I can sleep better at night. 🌒

This article is sponsored by the backtick conglomerate holding commonly referred to as “best practices”.

Liked the article? Subscribe below to get an email when new articles come out! Also, follow @ponyfoo on Twitter and @ponyfoo on Facebook.
One-click unsubscribe, anytime. Learn more.

Comments (34)

Nicolas Challeil wrote

The only thing stopping me to use backticks instead of single quotes is stupid french keyboard :) typing ‘`’ then ‘a’, for exemple, produce a ‘à’ :) It’s quite difficult to use :)

Ruben Deyhle wrote

Same problem with the german keyboard. However, at least on a mac, it is possible to disable those dead keys using the Mac App „Ukelele“.

But regarding „template literals only“ I wonder if there is no performance issue. I would believe that it is more expensive to parse template literals than just plain strings. That’s why I use template literals only when „needed“.

Nicolás Bevacqua wrote

Performance is a moot point. You’re probably already using a lot of other ES6 features that impact performance more heavily than template literals ever could. Besides, in browser code you’re transpiling template literals into plain old string concatenation, so there’s no performance impact whatsoever in the transpilation scenario.

Kai Dorschner wrote

Does it help to type the backtick and hit space right after that?

Nicolas Challeil wrote

yes it helps, but it’s two keypress for one char, not as fast than a ' (but yes, that’s what I do for now)

Fun fact, all usefull accentued char in French, on a French keyboard, have also a dedicated key. I never need the ` key until es6 :)

Delapouite wrote

Hi Nicolas.

Have a look at this custom keyboard layout, it will solve your issue : https://fabi1cazenave.github.io/qwerty-lafayette/

Niklas Bergius wrote

Or simply switch to the standard US layout for coding. Takes a couple of weeks to get used to it, makes everything much easier in pretty much every language. They were designed for US QWERTY. Your hands and wrists will thank you.

Giacomo Cosimato wrote

I simply switched to a keyboard with US layout at work. On Windows you can still write accented letters by hitting Win+spacebar to switch to international layout when needed. This allows you to write i.e. é by typing ’ and then e

Chris Coyier wrote

I love the Magic analogy.

Why use a 2/1 for 1🌳 when there is a flying 2/1 with trample for 1🌳 ?

Buzinas wrote

I prefer to use single quotes and only use template literals when:

  1. I’ll be interpolating
  2. It’s a multiline string
  3. The string has a single quote inside it

The main reasons I do this are:

  1. It’s much much simpler in my keyboard to type ’ than `, because I need to press shift + press the key + hit the space bar (Portuguese Brazilian keyboard)
  2. I think it’s more readable: the same way I always use const and only use let when my variables will change, I prefer to assume what my string is as soon as I look them.

In fact, if you think that using template literals is always better, you should also think that using let is always better, since you don’t need to think if your variable will change over time or not, etc.

Gustavo wrote

But there is a benefit to using const over let since const should complain when you try to reassign it. Therefore let isn’t strictly better. I do get your point though but honestly it’s easier to spot when there is ${interpolation} occurring than wether it’s a back tick or single quotes.

Buzinas wrote

In fact, Gustavo, my IDE uses different colors for back tick strings :)

Jon wrote

While I do love me some template literals for all the reasons you’ve described above, my one issue with this post is you’re arguing from the exact opposite point of view from the argument to use const over let. Using const is great because the purpose of the variable is limited to no reassignment, and block scope. You could argue the same with simple strings over template literals; single quotes are emphatically not for string interpolation, which means it’s harder to let a variable slip in there accidentally. And if you’ve ever worked in php, you’ll recognize this as a real problem. Admittedly, php’s interpolation syntax is much looser, but I can’t tell you how many times I used to let unescaped variables through my php template strings as a junior programmer. Stricter strings just don’t have that problem.

Marc wrote

In general, it seems to be best to use single quotes (’) for string literals and templated strings for concat.

This is the best of both words.

If you are worried about the performance overhead this as good as any other solution. For single quoted strings, these are immutable and has as little overhead as a string can have. The argument that speed doesn’t matter since you need to transpile anyway is poor because as ES6 is adopted on enough browsers (or in the node version you use) this will be among the features we will turn off transpilation for and will pay whatever the native cost is.

I do strongly agree that for code that has variables in it or want to use advanced features, backticked string are much more readable in most cases and will be at least as easy to optimize as the other solutions. The big winner for me is the ability to do a tagged template.

Brook Monroe wrote

Oh yeah–my first response to that was “yes, and one day I won’t be transpiling.”

Yevgen wrote

Thanks for sharing, Nicolas. Good points to think about. I didn’t know that the call like encode/<!doctype html>/`` is allowed. Although it is a valid syntax to me it makes code less readable, any benefits of using this approach?

Nicolás Bevacqua wrote
Patrick McElhaney wrote

It’s true that back ticks are harder to type. However, if you set up ESLint in your editor you can have it convert single quotes to back ticks automatically. In that case you could always type single quotes and not worry about typing back ticks even when you need a template literal.

In theory, there’s a performance hit using template literals for static strings. But I doubt it matters in practice. That’s an easy case for the compiler to optimize.

I’m having a hard time coming up with a counter to his article. Template strings everywhere might look weird, but so did arrow functions and object shorthand until I got used to them (which only took a few days).

Great article. I’ll likely be joining the ranks of the Ordre du Templates soon.

gotofritz wrote

The majority of the community has implicitly agreed on using const as the default over var. Eh? Did I miss a demo?

The const statement makes your code more clear, by describing a read-only value at declaration time. It also makes it clear that the variable isn’t meant to be used before its declaration, avoiding silly mistakes that could occur when using var. For these reasons, const also improves interaction with static analysis tools such as eslint. It is a read-only value IF A PRIMITIVE, otherwise you can easily change it. And Object.freeze doesn’t help.

I think const is actually more confusing, because it suggests a variable is frozen when it isn’t. I only use const for primitives or instances of truly immutable objects created with various libraries.

Brook Monroe wrote

Meh. It’s no worse than “const pointer” versus “pointer to const” in C++. I use const on function instantiations and anything whose fundamental nature isn’t going to change. (JavaScript is a language where people feel free to write a function with multiple return types–and one of those return types will always be undefined. Seriously, we need const.)

Jack wrote

What about server side performance vis-à-vis PHP and single quotes vs double quotes?

wheresrhys wrote

Well argued - I’m convinced

For the sake of completeness though you missed that ${myNonExistentVariable} or ${myExistentVariable will error, whereas the equivalent single or double-quoted strings won’t

Nicolás Bevacqua wrote

The number of times I wanted strings with such expressions – without the intent of interpolating JavaScript expressions into a template literal – is zero, so I didn’t feel like it was even worth bringing up. 😅

Nathan wrote

Using + is a bit noisier than using ,

It is? Why? They’re both one character, and + is a more semantic reflection of what you’re actually trying to achieve, so in my opinion , is noisier because it needs the associated array and .join() to work.

and we’d have to hand-roll our \n

Yes, assuming we are actually trying to create a string containing newlines. But often we’re concatenating smaller strings just to interpolate variables and/or for code readability. (Or as you mentioned, if building a string of HTML it doesn’t matter.)

Obviously using template literals solves all of the above, but still with regard to single or double quoted strings those reasons don’t make sense to me.

Half of respondents still use single quotes, where close to half claim to be prefer template literals.

I understand that you are just reporting on the responses you received, but how many people responded? That result would mean only a tiny fraction of people are using double quotes, but I know lots of people who prefer double quotes (usually because they have to use double quotes in Java or other languages and find it easier to stick with double quotes everywhere).

Alexander Gabriel wrote

When setting "quotes": ["error", "backtick"] in .eslintrc combined with eslint --fix I get this error:

ESLint Error: valid-typeof: Typeof comparisons should be to string literals

as --fix has set string ===string``

Is ESLint to eager or should backticks not be used in this case?

Nicolás Bevacqua wrote

I think that’s just the valid-typeof rule being a noisy neighbour 😅

Herbertusz wrote

I wonder why single quotes get 5 times more votes than double quotes.

Alasdair Shepherd wrote

Because it’s been considered a best practice for a very long time. When you’re coding for the browser your JS lives alongside HTML. Your HTML attributes may have JS code inside them, and your JS strings may have HTML inside them. It makes sense to have one type of string for one, and another for the other. And although it’s not mandatory anymore, the convention is still to put double quotes for HTML attributes. So JS gets single quotes.

Kai Dorschner wrote

Cool thing with template literals is, you can use them to produce SQL prepared-statements. Use this snippet to your liking:

export function query(queryParts, ...params) {
  return sql.preparedStatement(queryParts.join('?'), params); // return a promise pls
}


(async function () {
  const articles = await query`SELECT * FROM articles WHERE author_id = ${user.id}`;
  somehowProcessArticles(articles);
})();

A. Matías Quezada wrote

There are two reasons I use single quotes instead of backtick:

First one is spanish keyboard has the same issue as Nicolas Challeil said about french keyboard: àèìòù.

Second and most important one:

Why do you use const instead of let? Because with const you tell the developer: “Don’t look for assignations for this variable, they don’t exist”

Using single quotes instead of backtick you’re telling the developer “Don’t look for interpolation or multiline on this string, they don’t exist”.

Kyle Simpson wrote

I’ll just leave this gist here for posterity consideration.

Aaron Cordova wrote

Is there any overhead associated with backticks as opposed to single-quotes? Like, are there any real-world performance implications?

Nicolás Bevacqua wrote

While I don’t have data on that, I wouldn’t expect any overhead. Parsers can easily transform template literals into plain strings. If there’s an expression interpolation then they can just concatenate strings. If there’s a tagged template, then they can wrap things in function calls — which would be exactly what you’d do if you weren’t using tagged templates.

Joe Morgan wrote

Another problem with multi-line strings using single or double quotes is that if you accidentally have a space after the escape, you’ll get an error that can be very hard to track down (unless you have some kind of trailing spaces plugin in your editor that highlights or removes them automatically).

This is actually an example Crockford used as part of his many justifications for the opinionated nature of JSLint, and it’s still pretty relevant today.