That is, I know that when you write tag`Foo ${'bar'}.`;
, that’s just syntactic sugar for tag(['Foo ', '.'], 'bar');
.¹
But what about just `Foo ${'bar'}.`;
? I can’t just “call” (['Foo ', '.'], 'bar');
. If I already have arguments in that form, what function should I pass them to?
I am only interested in the native function that implements the template literal functionality. I am quite capable of rolling my own, but the purpose of this question is to avoid that and do it “properly”—even if my implementation is a perfect match of current native functionality, the native functionality can change and I want my usage to still match. So answers to this question should take on one of the following forms:
The name of the native function to use, ideally with links to and/or quotes from documentation of it.
Links to and/or quotes from the spec that defines precisely what the implementation of this function is, so that if I roll my own at least I can be sure it’s up to the (current) specifications.
A backed-up statement that the native implementation is unavailable and unspecified. Ideally this is backed up by, again, links to and/or quotes from documentation, but if that’s unavailable, I’ll accept other sources or argumentation that backs this claim up.
raw
property, since it’s a TemplateStringsArray
rather than a regular array, but I’m skipping that here for the sake of making the example more readable.I am trying to create a tag function (tag
, say) that, internally, performs the default template literal concatenation on the input. That is, I am taking the TemplateStringsArray
and the remaining arguments, and turning them into a single string that has already had its templating sorted out. (This is for passing the result into another tag function, otherTag
perhaps, where I want the second function to treat everything as a single string literal rather than a broken up template.)
For example, tag`Something ${'cooked'}.`;
would be equivalent to otherTag`Something cooked.`;
.
The definition of tag
would look something like this:
function tag(textParts, ...expressions) {
const cooked = // an array with a single string value
const raw = // an array with a single string value
return otherTag({ ...cooked, raw });
}
Defining the value of raw
is fairly straightforward: I know that String.raw
is the tag function I need to call here, so const raw = [String.raw(textParts.raw, ...expressions)];
.
But I cannot find anywhere on the internet what function I would call for the cooked
part of it. What I want is, if I have tag`Something ${'cooked'}.`;
, I want const cooked = `Something ${cooked}.`;
in my function. But I can’t find the name of whatever function accomplishes that.
The closest I’ve found was a claim that it could be implemented as
const cooked = [expressions.map((exp, i) => textParts[i] + exp).join('')];
This is wrong—textParts
may be longer than expressions
, since tag`Something ${'cooked'}.`;
gets ['Something ', '.']
and ['cooked']
as its arguments.
Improving this expression to handle that isn’t a problem:
const cooked = [
textParts
.map((text, i) => (i > 0 ? expressions[i-1] : '') + text)
.join(''),
];
But that’s not the point—I don’t want to roll my own here and risk it being inconsistent with the native implementation, particularly if that changes.
The name of the native function to use, ideally with links to and/or quotes from documentation of it.
There isn't one. It is syntax, not a function.
Links to and/or quotes from the spec that defines precisely what the implementation of this function is, so that if I roll my own at least I can be sure it’s up to the (current) specifications.
Section 13.2.8 Template Literals of the specification explains how to process the syntax.