Gabriel Rufino
Gabriel Rufino's Blog

Gabriel Rufino's Blog

Converting class instances to primitives

How you can use Symbol.toPrimitive to customize the conversion to primitives

Gabriel Rufino's photo
Gabriel Rufino
·May 15, 2022·

2 min read

Converting class instances to primitives

Photo by Krys Amon on Unsplash

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

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:

Did you find this article valuable?

Support Gabriel Rufino by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
 
Share this