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?
(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