Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Tagged template literal helper to regenerate the string
title tags date
Using template tags for simple logging
tags, javascript, logging
08-01-2020

Tagged template literal helper which regenerates the string

Often times I've wanted to utilize Tagged Template Literals to make writing logs super easy. This has often alluded me due to the structure of tags.

Tags expect a function which look like tag(strings?: Requireable<string>[], ...variables: any[]): any and passes the parts of the string to it when used; where a string Why hello ${firstName} ${lastName}! How are you? get converted into some representation of tag(["Why hello ", " ", "! How are you?"], firstName, lastName).

This is nice when you're doing some advanced parsing, but not neccessary for simple logging.

Usage

Usage of this helper is straight forward. useString takes an optional callback and will return a new tag which converts the input to the original string.

Callback

Let's take the scenario that started this off for me. I wanted to simplify my logging so tagging strings rather than "calling" functions. This is useful in a couple of ways, firstly it reduces friction which increases the amount of logging and decreases console.log pollution; secondly it allows us to manage the logger and enhance it as desired.

// Build the logger
const logger = (service, type = 'log') => useStringTag(string => {
  console[type](`[${service}] ${new Date().toISOString()} ${string}`)
});

// Create the tags
const workerLog = logger('worker');
const workerWarn = logger('worker', 'warn');
const workerError = logger('worker', 'error');

// Run the logs
workerLog`📻 Beep boop`;
workerWarn`❗️ Pay attention to this!`;
workerError`🚨 Woah nelly!`;

Async

This also works with async.

// Build the async tag
const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));
const doAsync = useStringTag(async string => {
  const ms = Math.round(Math.random() * 100 + 100)
  await wait(ms);
  return `${string} [took ${ms}]`;
});

// Run the work
doAsync`hello there`.then(console.log)

Fallback use with no callback

One might wonder why make the callback optional. I don't have a good use case, but I didn't want to throw an error.

// Create a new `str` tag
const str = useStringTag()

const friend = 'bob'
const result = str`hello ${friend}` // hello bob
// This is the same as: const result = `hello ${friend}`
function useStringTag(cb) {
const join = (strings, args) => strings.map((string, i) => string + (args[i] || '')).join('');
return (strings, ...args) => typeof cb === 'function' ? cb(join(strings, args)) : join(strings, args);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.