Proposal: Add `NoSubstitutionTemplate` to `StringLiteral` Definition

# FERREIRA, ERIC B (2 months ago)

Some teams opt to use exclusively template strings in their code (see template literals are strictly better stringsponyfoo.com/articles/template-literals-strictly-better-strings for some reasoning).

This is almost supported by ECMA, but for the fact that StringLiteraltc39.github.io/ecma262/#prod-StringLiteral is expressly defined as either a single quote or double quote string, excluding NoSubstitutionTemplatestc39.github.io/ecma262/#prod-NoSubstitutionTemplate.

I contend that adding NoSubstitutionTemplatestc39.github.io/ecma262/#prod-NoSubstitutionTemplate to the definition of StringLiteraltc39.github.io/ecma262/#prod-StringLiteral will bring the benefit of allowing teams to completely opt to use only template strings instead of mixing quote marks, while having very little risk or downside, if any at all.

NoSubstitutionTemplatestc39.github.io/ecma262/#prod-NoSubstitutionTemplate by nature are completely defined at "compile" time, essentially being exact same in functionality as standard StringLiteralstc39.github.io/ecma262/#prod-StringLiteral. Let's make it so in the grammar as well?

# T.J. Crowder (2 months ago)

On Wed, Jan 9, 2019 at 5:36 PM FERREIRA, ERIC B <EF183V at att.com> wrote:

I contend that adding NoSubstitutionTemplates to the definition of StringLiteral will bring the benefit of allowing teams to completely opt to use only template strings instead of mixing quote marks, while having very little risk or downside, if any at all.

I've been toying with defaulting to template literals for some time. :-)

Interesting idea. Where specifically do you see benefits of this change? The only places that immediately jump out to me are

  • "use strict", mentioned in your linked article
  • Quoted property names in object initializers (aka "object literals") -- oddly not mentioned in that article (it mentions JSON, but not object initializers)

That second one could be a bit of a footgun for people, who may trip over this working:

const obj = {`I have a space`: `bar`};

...but this failing:

const obj = {`I have a space ${x}`: `bar`};

...because that's not a NoSubstitutionTemplate and so it needs to be a computed property name.

Are there other places?

-- T.J. Crowder

# Jordan Harband (2 months ago)

import path specifiers are another.

# Andrea Giammarchi (2 months ago)

I dare saying tags are another issue here, 'cause "abc" === "abc", and with an identity function such const id = o => o, id("abc") === id("abc")

but due latest changes to template literals, idabc !== idabc so it's easily misleading in the tagged case.

# T.J. Crowder (2 months ago)

On Wed, Jan 9, 2019 at 7:40 PM Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:

I dare saying tags are another issue here, 'cause "abc" === "abc", and with an identity function such const id = o => o, id("abc") === id("abc") but due latest changes to template literals, idabc !== idabc so it's easily misleading in the tagged case.

Very good point, but at least tagging is its own thing.

What "recent changes" are you referring to? Surely

id`abc` === id`abc`

with that version of id was always false? You can't reuse the array from the first call to call the tag function the second time, what if the function modified the array? (Presumably if it is a change, that's why it was changed... :- ) )

-- T.J. Crowder

# Mark Miller (2 months ago)

Template is transitively frozen, so it cannot be mutated in place.

# Isiah Meadows (2 months ago)

The first argument to each is an array of items. It's the same per lexical occurrence, but it's not the same across multiple lexical templates, even if they represent the same sequence of characters with interpolation expressions removed. That above expression is semantically more like this: id(Object.assign(["abc"], {raw: "abc})) === id(Object.assign(["abc"], {raw: "abc})), which obviously should evaluate to false.


Isiah Meadows contact at isiahmeadows.com, www.isiahmeadows.com