Why are template strings not allowed in optional chaining?

Optional chaining grammar contains these productions:

OptionalChain :
  ?. TemplateLiteral
  OptionalChain TeplateLiteral

But then instead of defining runtime semantics, it makes these early errors. There's a note explaining the purpose is to maintain consistency with code without optional chaining.

String.raw`\t`; // works
String?.raw`\t` // syntax error

foo`x`; // works
foo?.`x`; // syntax error

Wouldn't it be more consistent if it simply worked (after null check) like a tagged template without optional chaining?

Possibly because

obj.prop`\t`

is

(obj.prop)`\t`

so

obj?.prop`\t`

would be

(obj?.prop)`\t` // possibly resulting in (undefined)`\t`

and calling undefined as a tagged template literal throws a TypeError.

So while

foo?.`x`

on its own may make sense, it may be confusing that a longer optional chain wouldn't compose with other features commonly paired with optional chaining like ??.

I don't think those would be equivalent. For plain function calls, we have:

obj?.prop('x') // undefined if obj is nullish, throws if obj.prop is nullish
obj?.prop?.('x') // undefined if obj?.prop is nullish
(obj?.prop)('x') // throws if obj?.prop is nullish

Tagged template is basically syntax sugar for function call, so I would expect:

obj?.prop`x` // undefined if obj is nullish, throws if obj.prop is nullish
obj?.prop?.`x` // undefined if obj?.prop is nullish
(obj?.prop)`x` // throws if obj?.prop is nullish

There seems to be a dedicated issue where this was discussed as part of optional chaining design here:

Thanks, that explains a lot.

1 Like