ValueObjects are only identified by their values, (for example money is a value object as long as we are not tracking individual banknotes, if we need to track individual banknotes then it should be a banknote entity)
Basically, they are all the attributes you need to validate the status and they don't have a unique ID
Copy import { Result, ValueObject } from 'types-ddd';
interface Prop {
value: string;
}
class EmailValueObject extends ValueObject<Prop> {
private constructor(prop: Prop) {
super(prop);
}
get value(): string {
return this.props.value;
}
public static isValidEmail (email: string): boolean {
const regex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/g;
return regex.test(email);
}
public static create(value: string): Result<EmailValueObject> {
const isValid = EmailValueObject.isValidEmail(value);
if (!isValid) {
return Result.fail<EmailValueObject>('Invalid email');
}
return Result.ok<EmailValueObject>(
new EmailValueObject({ value: value.toLowerCase() }),
);
}
}
Copy const emailOrError = EmailValueObject.create("valid_email@domain.com");
console.log(emailOrError);
> Result: {
"isSuccess": true,
"isFailure": false,
"error": null,
"statusCode": "OK",
"statusCodeNumber": 200,
"_value": {
"props": {
"value": "valid_email@domain.com"
}
}
}
Copy const emailOrError = EmailValueObject.create("invalid_email");
console.log(emailOrError);
> Result: {
"isSuccess": false,
"isFailure": true,
"error": "Invalid email",
"_value": null,
"statusCodeNumber": 422,
"statusCode": "UNPROCESSABLE_ENTITY"
}
You always have to validate if the result is a failure before getting the result
Copy emailOrError.isFailure;
> false
Copy const emailOrError = EmailValueObject.create("valid_email@domain.com");
const emailValueObject = emailOrError.getResult();
console.log(emailValueObject.value);
> "valid_email@domain.com"