{ES/TS} bit of the day: Typed Tagged Templates
Timothée Clain
Posted on December 28, 2018
Hi there! Today I'd like to talk about one of my beloved modern
javascript features. These are Tagged Templates.
Tagged What?
Basically Tagged Templates are an extension of the basic interpolation mechanism that you normally uses in ES6+.
Using backticks
you can elegantly insert values in a string (multiline by the way, :-))
const greet = (name) => `hello ${name}`
greet('timothee') // hello timothee
In one work?
By using the backticks notation with a function identifier, you basically have a template engine for free.
An example please!
Don't worry, it's actually less scary than what it sounds.
Let's take a function like
function myTemplate() {}
We'll see the actual arguments later.
I can call the function with this syntax now.
myTemplate`Hello !`
Weird isn't it?
What's more interesting, is I can actually pass interpolations with the familiar ${}
syntax.
Let's try it:
const externValue = "Timothee"
myTemplate`Hello ! ${externValue}`
Of course, I now can use computed values from the surrounding scope of my function call.
This syntax is an actual function call of myTemplate
So what's the magic actually?
Let's see the arguments passed to the function:
- The first argument is a list of invariant strings
- the
n
others arguments are all the other interpolation produced by${}
usage.
For instance, if I make this call:
myTemplate`Hello,${"Timothee"},World`
The first argument will be a list of all strings that don't change inside the passed string:
["Hello,", ",World"]
Of course, if you don't use any interpolations, you will have one element inside this array, the entire passed string.
The next argument will be my first interpolation, here it's a constant string: Timothee
.
So if we have n
interpolation in our template string, we all have n+1
elements in our first array, and n
more arguments passed to the function.
Cool, but how is it useful?
Whenever you need to apply transformations to a string with interpolation (aka dynamic values), this can be very useful.
For instance, you could build a template engine respecting the native semantics of es6
html`<h1>Hello ${name}</h1>`;
Actually, this already exists: https://lit-html.polymer-project.org/
In the react context, this technique is used to generate pre-styled components from CSS code for CSS-in-js solutions as emotion
or styled-components
.
const PrestyledComponent = styled('div')`
/** real css here */
background-color: blue;
`
// usage
const Fragment = <PrestyledComponent />
How can we type tagged templates
In typescript, we can add type information to our tagged templates:
function tagged(strings: TemplateStringsArray, ...args: boolean[]){
console.log(args)
}
The idea is to type the first argument as the TemplateStringsArray
type and the subsequent interpolations to whatever you need.
Let's take an example. Let's say you want to have auto-completable access to your theme from a styled component
export const theme = {
'colors.hello': true
}
export type ThemeKeys = keyof typeof theme
function themedStyled(strings: TemplateStringsArray, ...args: ThemeKeys[]){
console.log(args)
}
themedStyled`
background-color: ${};
`
And you got auto-completion of your theme keys for free!
That's it for today. Till next time!
Posted on December 28, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.