Is it possible to interpolate a template string using data from an object in JavaScript?

36 Views Asked by At

Is it possible to interpolate a template string using key/values from a object in JavaScript, like string substitution in Python:

data = {"age": 18, "name": "John"}
"I'm %(name)s. I'm %(age)d years old" % data       # "I'm John. I'm 18 years old"

One way that I can think of is using the with statement,

let data = {age: 18, name: "John"}
with(data){`I'm ${name}. I'm ${age} years old`}

but with is highly not recommended, it is neither efficient nor safe.

Is there a better way?

3

There are 3 best solutions below

2
Adnan On

You can destruct data object:

let data = {age: 18, name: "John"}
function with({name,age}){ return `I'm ${name}. I'm ${age} years old`; }

or do this:

let data = {age: 18, name: "John"}
function with(data){return `I'm ${data.name}. I'm ${data.age} years old`;}
0
FaniX On

I realized that there is a major difference between Python's string substitution and JavsScript's template string.

  • The template string in Python is exactly a string, it is only substituted when % is called,
  • while the template string in JS is substituted at the time it is declared and evaluated.

So, the answer could be different in different scenarios:

If I simply want to interpolate a template string with a specific object named data, I can simply use

`I'm ${data.name}. I'm ${data.age} years old`

If I want to declare a template string, and interpolate it using different objects, I can use a function:

(_=>`I'm ${_.name}. I'm ${_.age} years old`)(data1)    // `data1` can also be `data2` or `person3`

If I want to have some more elegent template strings, and make it somewhat programmable, I can use a tag function:

function interpolate(strings, ...keys){
    return function(obj){
        let i
        let result=""
        for(i=0;i<keys.length;i++){
            result+=strings[i]+obj[keys[i]]
        }
        return result+strings[i]
    }
}
// or an inline version, some difference in `undefined` value handling:
interpolate=(strings,...keys)=>(obj=>new Array(keys.length*2+1).fill().map((_,i)=>i&1?obj[keys[i>>1]]:strings[i>>1]).join(""))
// usage
interpolate`I'm ${"name"}. I'm ${"age"} years old.`(data)
0
Ashan On

You can do it like this I'm ${data.name}. I'm ${data.age} years old You should use this inside backticks (``).