This is one of the building blocks in Domain Model Pattern. It is an immutable type that is defined by its properties and doesn’t have any unique identity. They help to centralise the business logic for values manipulation but also, they express the business domain and speak the ubiquitous language. Object values should be used whenever you can as they make your code safer and encapsulates everything into one object.

Example

class Money {  
  private readonly amount: number;  
  private readonly currency: string;  
  
  constructor(amount: number, currency: string) {  
    if (amount < 0) {  
      throw new Error('Amount cannot be negative');  
    }  
    if (currency.length !== 3) {  
      throw new Error('Currency must be a 3-letter ISO code');  
    }  
    this.amount = amount;  
    this.currency = currency.toUpperCase();  
  }  
  
  public getAmount(): number {  
    return this.amount;  
  }  
  
  public getCurrency(): string {  
    return this.currency;  
  }  
  
  public equals(other: Money): boolean {  
    return this.amount === other.amount && this.currency === other.currency;  
  }  
  
  public add(other: Money): Money {  
    if (this.currency !== other.currency) {  
      throw new Error('Cannot add different currencies');  
    }  
    return new Money(this.amount + other.amount, this.currency);  
  }  
  
  public toString(): string {  
    return `${this.amount.toFixed(2)} ${this.currency}`;  
  }  
}  

How to check if Object Values are the same

Value objects do not have any identifier, so they need to be compared by their attributes.

// Example usage and comparisons  
const tenUSD = new Money(10, 'USD');  
const anotherTenUSD = new Money(10, 'USD');  
const twentyUSD = new Money(20, 'USD');  
const tenEUR = new Money(10, 'EUR');  
  
// Comparing equal amounts and currencies  
console.log(tenUSD.equals(anotherTenUSD)); // true  
  
// Comparing different amounts, same currency  
console.log(tenUSD.equals(twentyUSD)); // false  
  
// Comparing same amounts, different currencies  
console.log(tenUSD.equals(tenEUR)); // false  

Mutation of Value Objects

Because Value Objects cannot be mutated, you have to create a new instance of the thing you are creating. Because of that, you have to make sure that properties of Money are private and you only expose a method to create a new instance

// Example usage and comparisons  
const tenUSD = new Money(10, 'USD');  
const moreUSD = tenUSD.add(10, 'USD') // This is ok  
tenUSD.currency = "GBP" // This is not ok