Last active
April 7, 2025 10:50
-
-
Save ebidel/5e56a516e93ae0d9286c to your computer and use it in GitHub Desktop.
"ES6 meta programming" using tagged template strings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ES6 meta programming ??? | |
// The more complex form of ES6 template strings are called | |
// "tagged" template strings. In short, they allow you to | |
// pass the final evaluated string to a function for further | |
// processing. This allows for some interesting things. For example: | |
// | |
// get`https://api.github.com/repos/${org}/${repo}/issues?sort=${sort}`; | |
// | |
// _could_ make a network request and return a Promise with the result | |
// (instead of a string). | |
// | |
// Why would you want to do this? Well, you wouldn't! Users won't expect | |
// such side effects and returning a value other than a string is...bananas. | |
// | |
// That said, this type of ES6 magic is a fun POC :) | |
// Run this in Babel: https://goo.gl/NfgPq1 | |
function get(strs, ...values) { | |
// Reconstruct the final URL. If no substitutions were given, | |
// the original string is used. | |
let url = values.reduce((prev, curr, i) => prev + curr + strs.raw[i + 1], strs.raw[0]); | |
return fetch(url).then(response => response.json()).then(results => { | |
results.forEach(r => { | |
console.log(r.url, r.title); | |
}); | |
return results; | |
}); | |
} | |
let org = 'Polymer'; | |
let repo = 'polymer'; | |
let sort = 'updated'; | |
// Example 1 | |
get`https://api.github.com/repos/${org}/${repo}/issues?sort=${sort}`; | |
// Example 2 | |
// Note: we dropped the Promise on the floor in Example 1. | |
// get`https://www.chromestatus.com/features.json`.then(results => { | |
// results.forEach(r => console.log(r.name)); | |
// }); |
There are two things you can improve:
- Your code ignores text after the last
${}
. - You should be using raw text in the
reduce()
callback.
How about the following (note: strs.length === values.length+1
)?
function get(strs, ...values) {
// Reconstruct the final URL.
let url = values.reduce((prev, curr, i) => prev + curr + strs.raw[i+1], strs.raw[0]);
return ···
···
}
Thanks for that. I updated the snippet. Good call on #1.
You don’t need the if
statement (lines 24–26) anymore: reduce()
uses strs.raw[0]
whenever values.length === 0
.
Right right. Removed.
Is that syntax possible with every function then?
Maybe with Proxies? This was interesting to me because you can define a custom function to be called on your template string, but it's still used as a string. In this example, it's not doing any processing on the string and hijacking the return val to be something else.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Demo it in Babel: https://goo.gl/NfgPq1