Skip to main content

Command Palette

Search for a command to run...

Converting class instances to primitives

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

Published
2 min read
Converting class instances 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: