2
let x = ‽; // "‽" Could be any type(String, Array, Object, ...) The goal is to make the statement true 

`${x}` !=  '' + x // true

`${x}` !== '' + x // true

What should we assign to X to make the statements true?

I'm thinking it's not possible to make it true, but is there any exception?

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Pooria Han
  • 597
  • 1
  • 4
  • 19

2 Answers2

4

You need a value that serializes to a different value every time it's converted to a string.

const x = {
  [Symbol.toPrimitive]: (y => () => y++)(0),
};

console.log(`${x}` !== '' + x);
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Maybe a bit easier to understand for the OP: `x = { toString: () => String(Math.random()) }` - But of course unlike your solution, this one has a super-miniscule chance (1 in 9 quadrillions) of returning the same value twice - on the other hand, your solution has a 100% chance of returning the same value twice after 9 quadrillion iterations ^^ so it doesn't matter – CherryDT Apr 04 '21 at 12:18
  • 1
    Reminds me of [this](https://stackoverflow.com/q/48270127/1048572) trick question :-) – Bergi Apr 04 '21 at 12:25
  • @CherryDT: Yeah, I had `Math.random` first :D – Felix Kling Apr 04 '21 at 15:13
4

Felix's answer covers one absolutely valid approach, but I'll add another one here that doesn't require incrementing or random values.

`${x}`

converts x to a string using ToString, which in the case of x being an object, does ToPrimitive(argument, string).

'' + x

on the other hand uses ApplyStringOrNumericBinaryOperator, which does ToPrimitive(rval).

You can take advantage of that difference in the 2nd parameter of the function. For example:

x = {
  [Symbol.toPrimitive](hint) {
    if (hint === "string") {
      return 'a';
    } else {
      return 'b';
    }
  },
};

and now in this case

`${x}` === 'a' // true
'' + x === 'b' // true

You can also see this without Symbol by directly using toString and valueOf:

x = { 
  toString(){ return 'a'; }, 
  valueOf(){ return 'b'; },
};

which produces the same thing as the last example, because valueOf is the default unless a string value is explicitly hinted, as in the case for ${x}.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • I was actually wondering whether one of those two operations prefers "the other" conversion method first but didn't bother to look. Nice one. – Felix Kling Apr 04 '21 at 20:31
  • @FelixKling It's definitely not one I'd know either except that it came up as a bug for Babel's template string compilation way back, since it originally output a chain of `+` operations. – loganfsmyth Apr 04 '21 at 22:01