# String.identity template string tag

**URL:** https://es.discourse.group/t/string-identity-template-string-tag/2097
**Category:** 💡 Ideas
**Created:** [July 24, 2024, 6:34am UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097 "2024-07-24T06:34:57Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)
#### Post date: [July 24, 2024, 6:34am UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/1 "2024-07-24T06:34:57Z")

</div>

So that we don't have to write this:

```js
function identityTemplateTag(stringsParts, ...values) {
    let str = ''
    for (let i = 0; i < values.length; i++) str += stringsParts[i] + String(values[i])
    return str + stringsParts[stringsParts.length - 1]
}

```

Plus a built-in option could be more optimized.

This

```js
const result = String.identity`
  value: ${someValue}
`

```

would be essentially be identical to:

```js
const result = `
  value: ${someValue}
`

```

but then it is easy to simply opt into syntax highlighting in certain IDEs:

```js
const html = String.identity

// Various syntax highlighters will now highlight the content of
// the string as HTML code, out of the box:
const result = html`
  <div>foo</div>
`

```

Notice how even ES.Discourse's own syntax highligher highlighted the `html` content!

---

<div class="post-metadata">

### Author: ![aclaymore](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/aclaymore/32/501_2.png) [@aclaymore](https://es.discourse.group/u/aclaymore)
#### Post date: [July 24, 2024, 8:19am UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/2 "2024-07-24T08:19:27Z")

</div>

> [@trusktr](#):
>
> Notice how even ES.Discourse's own syntax highligher highlighted the `html` content!

Implementation here: [highlight.js/src/languages/javascript.js at 9267f5022c14bcd848b8a9024f8c88230fcf7b54 · highlightjs/highlight.js · GitHub](https://github.com/highlightjs/highlight.js/blob/9267f5022c14bcd848b8a9024f8c88230fcf7b54/src/languages/javascript.js#L136)

I think there are IDE extensions that can do the same but with a magic comment:

```javascript
let t = /* html */`<div></div>`;

```

---

<div class="post-metadata">

### Author: ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)
#### Post date: [July 24, 2024, 11:07am UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/3 "2024-07-24T11:07:44Z")

</div>

If your template contains a DSL, shouldn't you use `String.raw` for that? In HTML, `\n` is not a newline, it's a backlash followed by a letter.

MDN provides a one-liner for your escaped-identity:

> **[String.raw() - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw#building_an_identity_tag)**
>
> The String.raw() static method is a tag function of template literals. This is similar to the r prefix in Python, or the @ prefix in C# for string literals. It's used to get the raw string form of template literals — that is, substitutions (e.g....

---

<div class="post-metadata">

### Author: ![senocular](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/senocular/32/642_2.png) [@senocular](https://es.discourse.group/u/senocular)
#### Post date: [July 24, 2024, 12:15pm UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/4 "2024-07-24T12:15:20Z")

</div>

> **[GitHub - tc39/proposal-string-cooked: ECMAScript proposal for String.cooked built-in...](https://github.com/tc39/proposal-string-cooked)**
>
> ECMAScript proposal for String.cooked built-in template tag

---

<div class="post-metadata">

### Author: ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)
#### Post date: [July 26, 2024, 5:02am UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/5 "2024-07-26T05:02:54Z")

</div>

Ah, that's the word, "cooked"! Thanks!

---

<div class="post-metadata">

### Author: ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)
#### Post date: [July 28, 2024, 2:23pm UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/6 "2024-07-28T14:23:49Z")

</div>

IIRC that was slower than [plain-tag](https://github.com/WebReflection/plain-tag#readme) but snippet on MDN is indeed an easy way to obtain the same:

```js
const tag = (strings, ...values) => String.raw({ raw: strings }, ...values);

```

Probably time to ditch `plain-tag` in favor of this ... thanks for the hint.

* * *

**edit** plain-tag in a tweet:

```js
function tag(t) {
  for (var s = t[0], i = 1, l = arguments.length; i < l; i++)
    s += arguments[i] + t[i];
  return s;
}

```

---

<div class="post-metadata">

### Author: ![Josh-Cena](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/josh-cena/32/1408_2.png) [@Josh-Cena](https://es.discourse.group/u/Josh-Cena)
#### Post date: [July 28, 2024, 5:45pm UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/7 "2024-07-28T17:45:37Z")

</div>

The plain-tag one only works on "good-faith" input and doesn't deal with the tag not being used as a tag. But more importantly it uses the wrong coercion semantics too, for example you can't embed a `Temporal` instance and expect it to be coerced to string, because they have functional `toString` but throwing `valueOf`, and addition would call `valueOf` before `toString`.

---

<div class="post-metadata">

### Author: ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)
#### Post date: [July 29, 2024, 7:52am UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/8 "2024-07-29T07:52:49Z")

</div>

it's been working well for 4 years but yes, it doesn't expect fancy interpolations ... although all its dependent projects never complained about anything, it's supposed to be as minimal and as fast as possible. I will benchmark against the MDN suggested workaround though and update it if that results faster than it is now.

---

<div class="post-metadata">

### Author: ![WebReflection](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/webreflection/32/248_2.png) [@WebReflection](https://es.discourse.group/u/WebReflection)
#### Post date: [July 29, 2024, 3:14pm UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/9 "2024-07-29T15:14:24Z")

</div>

FYI these are the results:

**node**

```javascript
plain: 0.649ms
fake: 2.689ms
noop: 0.903ms
std: 0.922ms

```

**bun**

```javascript
[1.54ms] plain
[2.59ms] fake
[3.01ms] noop
[2.58ms] std

```

the std implementation is:

```js
const { raw: $ } = String;
const std = (raw, ...values) => $({ raw }, ...values);

```

In node the difference is not too bad but in bun it's 1 whole ms and that's concerning.

In browser I can observe similar slowness of the `raw` suggestion ... it's 0.5 up to 4ms slower compared to plain tag.

---

<div class="post-metadata">

### Author: ![lightmare](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/lightmare/32/843_2.png) [@lightmare](https://es.discourse.group/u/lightmare)
#### Post date: [July 30, 2024, 2:19pm UTC](https://es.discourse.group/t/string-identity-template-string-tag/2097/10 "2024-07-30T14:19:23Z")

</div>

Absolute differences in a micro-benchmark. I see ~50% slower and that may be acceptable, depending on use case. Btw your `benchmark.js` measures `noop` twice, and doesn't measure `std`.
