Value Objects
A Value Object is an immutable object that is defined by its value, not by identity.
Example:
- Two emails
"user@example.com"
are equal if their value is equal, even if they are different instances.
Real-life Analogy
Section titled “Real-life Analogy”Think of a €10 bill:
- It doesn’t matter which specific paper you hold — €10 is €10.
- The value is what matters, not the individual instance.
In contrast, a person is an entity — they have a unique identity, even if their name or attributes change.
Example in DomusJS
Section titled “Example in DomusJS”import { ValueObject } from '@domusjs/core';
export class Email extends ValueObject<{ value: string }> { private static readonly EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
private constructor(props: { value: string }) { super(props); }
get value(): string { return this.props.value; }
public static create(email: string): Email { if (!this.EMAIL_REGEX.test(email)) { throw new Error(`Invalid email format: ${email}`); } return new Email({ value: email }); }}
✅ This ensures:
- Emails are validated on creation.
- Comparisons are done by value, not by reference.
- They cannot be mutated after creation.
Benefits of Value Objects
Section titled “Benefits of Value Objects”- Encapsulate rules and validation → prevent invalid states.
- Increase expressiveness →
Email
orMoney
is clearer than juststring
ornumber
. - Immutability → once created, they never change.
- Simpler comparisons → compare by value, not reference.
Common Mistakes
Section titled “Common Mistakes”- Avoid adding identifiers or mutable fields to value objects — that turns them into entities.
- Keep them focused on representing a value with meaning, not behavior.