The double at sign (@@
) represents a "well-known symbol". The "[@@toPrimitive]()
" well-known symbol (introduced in ES6) denotes "Symbol.toPrimitive()
", which is used for specifying a class/object method that returns a primitive representation of an object. The Symbol.toPrimitive()
method is called with a string argument "hint
", which is equal to one of the following values:
"number"
: suggests the method was called as a result of a numeric coercion algorithm;"string"
: suggests the method was called as a result of a string coercion algorithm;"default"
: suggests the method was called as a result of a primitive coercion algorithm.
"[@@toPrimitive]()
" has great browser support, so you can implement it in your code with ease of mind.
A "Symbol.toPrimitive()
" method is the first object method that's called by all type coercion algorithms. Therefore, it can be used to convert an object to a primitive value.
For example, you can implement it in an object literal like so:
// ES6+ const obj = { [Symbol.toPrimitive](hint) { if (hint === 'number') { return 1234; } else if (hint === 'string') { return 'foo'; } return 'default'; } } console.log(Number(obj)); // 1234 console.log(+obj); // 1234 console.log(String(obj)); // 'foo' console.log(`${obj}`); // 'foo' console.log(obj + ''); // 'default'
Similarly, you can implement it as a class method in the following way:
// ES6+ class Foo { [Symbol.toPrimitive](hint) { if (hint === 'number') { return 1234; } else if (hint === 'string') { return 'foo'; } return 'default'; } } const foo = new Foo(); console.log(Number(foo)); // 1234 console.log(+foo); // 1234 console.log(String(foo)); // 'foo' console.log(`${foo}`); // 'foo' console.log(foo + ''); // 'default'
Using the "hint
" parameter is not required. Therefore, you may implement a "Symbol.toPrimitive()
" method without using it:
// ES6+ const obj = { [Symbol.toPrimitive]() { return 'foo'; } } console.log(Number(obj)); // NaN console.log(+obj); // NaN console.log(String(obj)); // 'foo' console.log(`${obj}`); // 'foo' console.log(obj + ''); // 'foo'
The reason coercion to number results in NaN
(in the example above) is because the resulting value from Symbol.toPrimitive()
method is a non-numeric value. On the flip side, if you return a number for string coercion, it will automatically coerce it to a numeric string:
// ES6+ const obj = { [Symbol.toPrimitive]() { return 1234; } } console.log(Number(obj)); // 1234 console.log(+obj); // 1234 console.log(String(obj)); // '1234' console.log(`${obj}`); // '1234' console.log(obj + ''); // '1234'
The "Symbol.toPrimitive()
" method must always return a primitive or a TypeError
is thrown.
Below is an example of "Symbol.toPrimitive()
" method returning a non-primitive value, which results in a TypeError
being thrown:
const obj = {
[Symbol.toPrimitive]() {
return {};
}
}
// TypeError: Cannot convert object to primitive value
console.log(+obj);
Hope you found this post useful. It was published . Please show your love and support by sharing this post.