2

is it possible to use an object spread inside a template string:

const obj = {
    key1: 'value1',
    key2: 'value2'
};

// contrived example to show that `obj` can also be dynamically constructed
for (let i = 0; i < 3; i++) {
    obj[`someKey${i}`] = i
}

const templateString = `{
    "templateKey1": "anotherValue1",
    "templateKey2": "anotherValue2",
    ${...obj}
}`

expected result:

console.log(templateString)
// should output an object in string format:
'{
    "templateKey1": "anotherValue1",
    "templateKey2": "anotherValue2",
    "key1": "value1", 
    "key2": "value2",
    "someKey0": 0,
    "someKey1": 1,
    "someKey2": 2
}'

I only get an Unexpected token error message when it tries compiling.

My project is using babel and the object spread plugin works as intended so the configuration is not incorrect.

hellatan
  • 3,517
  • 2
  • 29
  • 37
  • 3
    What are you exactly expecting to happen? – ichigolas Dec 26 '16 at 00:55
  • The spread operator used with an object is for _destructuring assignments_, what is your expected behaviour? – Paul S. Dec 26 '16 at 00:55
  • @nicooga - i updated the question to show the desired output – hellatan Dec 26 '16 at 01:00
  • If expected result is original object what is purpose for using rest element on object itself? – guest271314 Dec 26 '16 at 01:01
  • @PaulS. - i updated the question to show the desired output (it seems that SO only allows one mention per comment) – hellatan Dec 26 '16 at 01:01
  • I propose `console.log(obj)` as a solution! – therobinkim Dec 26 '16 at 01:01
  • _"contrived example to show that `obj` can also be dynamically constructed"_ The object reference will be same, yes? You are already populating the object with properties and values at `for` loop. Why is spread element necessary? – guest271314 Dec 26 '16 at 01:16
  • Are you trying to construct a plain object dynamically within template literal? – guest271314 Dec 26 '16 at 01:33
  • @guest271314 I'm using `react-helmet` and it requires it to use a template string for one of its properties. I updated the question again to show that there are already key/value pairs in the template string already, hence the need to do the object spread. It doesn't seem like i can just use a reference to the object for `react-helmet` otherwise i'd construct the entire object first then reference it. – hellatan Dec 26 '16 at 01:33
  • @hellatan Have not tried `React` or `react-helmet`. See also [What is this called in javascript? ({name, value}) => ](http://stackoverflow.com/questions/40470272/what-is-this-called-in-javascript-name-value-span-span). Are you trying to use [object spread properties](https://github.com/sebmarkbage/ecmascript-rest-spread/blob/master/Spread.md) within the template string expression? – guest271314 Dec 26 '16 at 02:08
  • 2
    FWIW, this is not objects spread because `${ }` doesn't denote an object. It's simply invalid code. – Felix Kling Dec 26 '16 at 08:32

2 Answers2

2

If expected result is original object, rest and spread element are not necessary to return expected result. Use JSON.stringify(), JSON.parse()

const obj = {
    key1: 'value1',
    key2: 'value2'
};

const templateString = `${JSON.stringify(obj)}`

console.log(JSON.parse(templateString));
guest271314
  • 1
  • 15
  • 104
  • 177
  • I updated the question to show that the object gets dynamic key/values generated as well – hellatan Dec 26 '16 at 01:06
  • @hellatan That does not change expected result. [`Template literals`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) are strings, not objects _"Template literals are string literals allowing embedded expressions."_. The object will get additional properties and values added. What is purpose of using spread element? What are you trying to achieve? Are you expecting `templateString` to be a string or a plain object? – guest271314 Dec 26 '16 at 01:08
  • doing this in my updated example would result in an object inside the object – hellatan Dec 26 '16 at 01:35
  • @hellatan Not sure what you mean? You have not yet described what exact expected result is? Are you expecting `templateString` to be a string or a plain object? – guest271314 Dec 26 '16 at 01:37
  • @hellatan You can still use `JSON.stringify()`; utilize `.replace()` given example at updated Question `${JSON.stringify(obj, null, 4).replace(/^\{|\}$/g, "")}` https://jsfiddle.net/5hkjyt6h/ – guest271314 Dec 26 '16 at 01:43
  • it would basically output the values into string format since, like you said, a template string is ultimately outputting a string. If i were to do the `JSON.stringify` within my template string, i get something like this: `{ "key1": "value1", "key2": "value2", { "spread1": 0, "spread2": 1 }}`. I think i can take this approach and do some additional string manipulation as the generators example would require additional setup to my build which I'm not sure if we want to add that extra code at this point in time. – hellatan Dec 26 '16 at 01:45
  • `{ "key1": "value1", "key2": "value2", { "spread1": 0, "spread2": 1 }}` is not valid `JSON` or `javascript` plain object. Do you mean `{ "templateKey1": "anotherValue1", "templateKey2": "anotherValue2", "spread": { "spread1": 0, "spread2": 1 } }` https://jsfiddle.net/5hkjyt6h/1/ ? – guest271314 Dec 26 '16 at 02:00
  • `{ "key1": "value1", "key2": "value2", { "spread1": 0, "spread2": 1 }}` - yes, i'm well aware of that :) – hellatan Dec 26 '16 at 03:57
  • @hellatan You are not expecting a `JSON` string or `javascript` object, but a generic string formatted in a particular manner? – guest271314 Dec 26 '16 at 04:01
0

Yes, it's possible. But

  • Objects are not iterable by default
  • You must spread to an array initializer or a function call

const obj = {
  key1: 'value1',
  key2: 'value2',
  [Symbol.iterator]: function*() {
    var indent = 4;
    yield JSON.stringify(this, null, indent).slice(2+indent, -2);
  }
};
for (let i = 0; i < 3; i++) obj[`someKey${i}`] = i;
console.log(`{
    "templateKey1": "anotherValue1",
    "templateKey2": "anotherValue2",
    ${[...obj]}
}`);
/* `{
    "templateKey1": "anotherValue1",
    "templateKey2": "anotherValue2",
    "key1": "value1",
    "key2": "value2",
    "someKey0": 0,
    "someKey1": 1,
    "someKey2": 2
}` */
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • 1
    This answer does a load of cool things, but don't do this. If you want a String, use `JSON.stringify`. If you just want to log, log directly. – Paul S. Dec 26 '16 at 01:23