/** * Base class for Value Objects in Domain-Driven Design. * * Value Objects are immutable objects that represent descriptive aspects of the domain * with no conceptual identity. They are defined by their attributes rather than a unique ID. * * Key characteristics: * - Immutable: Once created, they cannot be changed * - Equality by value: Two value objects are equal if all their attributes are equal * - Self-validating: They validate their own invariants upon construction * * @example * ```typescript * class EmailAddress extends ValueObject<{ value: string }> { * private constructor(public readonly value: string) { * super(); * this.validate(); * } * * public static create(email: string): EmailAddress { * return new EmailAddress(email); * } * * protected validate(): void { * const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; * if (!emailRegex.test(this.value)) { * throw new Error(`Invalid email address: ${this.value}`); * } * } * * protected* getEqualityComponents(): Iterable { * yield this.value; * } * } * * const email1 = EmailAddress.create("user@example.com"); * const email2 = EmailAddress.create("user@example.com"); * console.log(email1.equals(email2)); // true * ``` */ export default abstract class ValueObject { /** * Validates the value object's invariants. * This method is called automatically during construction. * Throw an error if validation fails. * * @throws {Error} When validation fails */ protected abstract validate(): void; /** * Returns the components that determine equality. * Override this method to specify which properties should be compared. * * @returns An iterable of values to compare for equality */ protected abstract getEqualityComponents(): Iterable; /** * Checks if this value object is equal to another. * Two value objects are equal if all their equality components are equal. * * @param other - The other value object to compare with * @returns True if the value objects are equal, false otherwise */ equals(other: ValueObject | null | undefined): boolean; /** * Deep equality comparison for components. * * @param components1 - First array of components * @param components2 - Second array of components * @returns True if all components are deeply equal */ private componentsAreEqual; /** * Deep equality check for individual values. * Handles primitives, arrays, objects, and nested value objects. * * @param value1 - First value to compare * @param value2 - Second value to compare * @returns True if values are deeply equal */ private isEqual; /** * Checks if a value is a plain object (not an array, Date, or class instance). * * @param value - The value to check * @returns True if the value is a plain object */ private isPlainObject; }