skip to Main Content

A simple template literal expression:

`${value}`

… will throw TypeError in at least two cases:

try {
  `${Symbol('nope')}`
} catch (error) {
  console.error(`${error.name}: ${error.message}`)
}
  • if value is an empty non-inherited object.
try {
  `${Object.create(null)}`
} catch (error) {
  console.error(`${error.name}: ${error.message}`) // weird error message in this case: "No default value"
}

What are the other cases in which it throws an error, if any? Is there some universal rule for that (like, not having some method used internally)?

2

Answers


  1. What are the other cases in which it throws an error, if any?

    There’s too many to count. Basically every object for which coercing it to a (string) primitive fails.

    Is there some universal rule for that (like, not having some method used internally)?

    Not a single method but three of them. The abstract ToString operation which is used in template literal evaluation (and everywhere else in the spec when a value needs to be coerced to a string – in particular for string concatenation, values to be used as property keys, and arguments that are expected to be strings) does

    • throw on symbols, as you noted

    • call the abstract ToPrimitive operation on obects, which in turn tries to call

      • o[Symbol.toPrimitive]("string")
      • o.toString()
      • o.valueOf()

      if these methods exist, until one of them throws or returns a non-object value, which then is fed to ToString. It also throws if none of these properties are methods.

    Login or Signup to reply.
  2. ${value} is perhaps an oversimplication of ${expression}, where expression is a Javascript expression that is first evaluated, and then converted to a string to be inserted in the template.

    It will throw if the result of the expression doesn’t support a toString method:

    • Symbol data types don’t support toString operations while other primitive data types do.
    • Objects which don’t have or don’t inherit a toString method from their inheritance chain will also throw because calling their toString method fails. Classic examples of this kind are either created by Object.create(null), or inherit from such an object with no toString methods defined in the inheritance chain. E.G.
    function test(result) {
      try {
        console.log( "result.toString(): ", `${result}`);
      }
      catch(err) {
        console.log( "(result, error): ", result, err.message);
      }
    }
    test(Symbol());
    test(Object.create(null));
    test({});

    It will also fail if the expression provided throws because of JavaScript errors. E.G.

    `${const x}`
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search