Converting class instances to primitives
How you can use Symbol.toPrimitive to customize the conversion to primitives
Sometimes it happens to convert objects/instances to primitives, intentionally or not. Let's suppose this class:
class ProductEntity {
constructor({ name, quantity, price }) {
this.name = name
this.quantity = quantity
this.price = price
}
}
Imagine that at some point in your code, you print a log for observability purposes. But you forget to suffix the property .name
in the log. Some like that:
const book = new ProductEntity({
name: 'Clean Code - Robert Cecil Martin',
quantity: 500,
price: 49.99
})
console.log(`Product ${book} is available for buying`)
The output will be Product [object Object] is available for buying
. You'll always get these values by default in primitive conversions:
- String -
"[object Object]"
- Number -
NaN
Look at the result of explicit conversions:
const book = new ProductEntity({
name: 'Clean Code - Robert Cecil Martin',
quantity: 500,
price: 49.99
})
console.log(Number(book)) // NaN
console.log(String(book)) // [object Object]
You can customize this behavior by adding the function [Symbol.toPrimitive]
in the class. This function allows returning a custom value according to the received type. The possible types are:
'default'
'number'
'string'
In this example, I'll choose to return the name for string conversion, the quantity for number conversion, and the true for default conversion.
Let's see the result:
class ProductEntity {
constructor({ name, quantity, price }) {
this.name = name
this.quantity = quantity
this.price = price
}
[Symbol.toPrimitive](type) {
if (type === 'number') {
return this.quantity
} else if (type === 'string') {
return this.name
} else {
return true
}
}
}
const book = new ProductEntity({
name: 'Clean Code - Robert Cecil Martin',
quantity: 500,
price: 49.99
})
console.log(Number(book)) // 500
console.log(String(book)) // "Clean Code - Robert Cecil Martin"
console.log(`The product ${book} has now ${Number(book)} unities`) // "The product Clean Code - Robert Cecil Martin has now 500 unities"
You can see more in: