davidchambers / string-format

JavaScript string formatting inspired by Python’s `str.format()`
Do What The F*ck You Want To Public License
334 stars 36 forks source link

Support type-based transformers #43

Open haykam821 opened 5 years ago

haykam821 commented 5 years ago

It'd be somewhat helpful to be able to automatically apply transformers based on the typeof for a value. For example:

const fmt = format.create({
  string: str => "'" + str + "'",
  number: num => num.toLocaleString(),
});
fmt("Welcome back, {}! You have {} unread messages.", "Alice", 1000); // Welcome back, 'Alice'! You have 1,000 unread messages.
davidchambers commented 5 years ago

I can think of three ways to achieve the desired result with the existing API. Hopefully you find at least one of these options satisfactory. :)

Option 1: Transformers

const fmt = format.create({
  string: str => "'" + str + "'",
  number: num => num.toLocaleString(),
});

fmt("Welcome back, {!string}! You have {!number} unread messages.", "Alice", 1000);

Option 2: Preprocessing via monomorphic functions

//    string :: String -> String
const string = str => "'" + str + "'";

//    number :: Number -> String
const number = num => num.toLocaleString();

format("Welcome back, {}! You have {} unread messages.", string("Alice"), number(1000));

Option 3: Preprocessing via polymorphic function

//    toString :: Any -> String
const toString = x => {
  switch (typeof x) {
    case "number":  return x.toLocaleString();
    case "string":  return "'" + x + "'";
    default:        throw new Error ("Not implemented");
  }
};

format("Welcome back, {}! You have {} unread messages.", toString("Alice"), toString(1000));
haykam821 commented 5 years ago

I suppose this (along with #16, but code for that is not included) could be fixed with a wrapper function:

const typeTransformers = {
    string: str => str.toUpperCase(),
    number: num => num.toLocaleString(),
};
function coolFormat(str, ...stuff) {
    return format(str, ...stuff.map(thing => {
        const transform = typeTransformers[typeof thing];
        if (typeof transform === "function") {
            return transform(thing);
        } else {
            return thing;
        }
    });
}
davidchambers commented 5 years ago

Good idea, @haykam821. :)