My First Useful Tagged Template Literal
Tags: javascript
Published: 2020-12-14 21:43:47

Since their inclusion in Javascript [tagged template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates) have had developers on edge about possible use cases for them. There are the [obvious](https://viperhtml.js.org/) [ones](https://lit-html.polymer-project.org/). For me they seemed soo useful. Yet I found myself looking for a problem to solve, instead of it being obvious they were the right tool for the job.

Very recently i think i’ve happened upon a problem they solve elegantly.

So the background story is I am working on a large scale SPA project. This project interfaces with an api server. Nothing unusual there.

What is unusual is the `id` for a lot of these resources is actually user submitted text strings. They have to be unique, not include certain characters etc, but the key is “its user submitted text”. We had no option to change this (at least for now).

This creates what is at least for me an unusual situation. The api resource urls can contain certain “must be encoded” characters (spaces, commas, full stops, accents).

## The Existing Solution

Another lead developer on the project created a solution i’ve seen before to construct the url, and escape the correct variables using indexed replacement from an array.

```javascript
['/api/v1/{0}/{1}', varName, anotherVar]
```

This solution works and we have been using it successfully for a while now.

Alongside this a VueJs mixin was created which did some further magic to make replacements directly on a string using something similar to literal syntax: `/api/v1/{varName}`. Where `varName` could be accessed directly off the Vue instance.

The problem with these 2 methods are:

1. The array syntax feels awkward
2. Option 2 (the clearer option) can only be used inside a component instance, not for example in a store module
3. A limitation of option 2 is that it requires the “vars” used in the string be accessible on `this`
4. Option 2 caught a few members of the team out, thinking it was actually a string literal when they started to reuse from examples

### The (possible) Tagged Template Literal Solution

So i had a bit of an idea, it takes the existing concept further and addresses some of the issues.

1. It does use a template literal with a tagged function
2. Its clearer than the array syntax
3. The vars can be anything you have access to, as its a literal any javascript inside placeholders `${}` works.
4. It can be used from anywhere

Usage is very much the same as before (via the mixin), you just convert the string to a literal, prepend the tagged function `url` and you use real placeholder syntax `${}`.

```javascript
// Existing solution (result not implementation)
const existingWay = theUrlConstructor([
    '/api/v1/resource/{0}/{1}',
  'my string, with unsafe',
  'url +characters+'
])
// /api/v1/resource/my%20string%2C%20with%20unsafe/url%20%2Bcharacters%2B
// New solution
const url = (strings, ...values) => {
    return strings.reduce((compiled, string, index) => {
    return compiled.concat(string, encodeURIComponent(values[index] || ''))
  }, []).join('')
}
const first = 'my string, with unsafe'
const second = 'url +characters+'
const newWay = url`/api/v1/resource/${first}/${second}`
// /api/v1/resource/my%20string%2C%20with%20unsafe/url%20%2Bcharacters%2B
```

I’ve introduced this to the team, but haven’t yet had any real feedback, let me know what you think.