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"