Test on Playground
This approach was used in a clean architecture example, available here
| // Value object | |
| class CityName { | |
| static readonly MIN_LEN_NAME: number = 3 | |
| static readonly MAX_LEN_NAME: number = 100 | |
| private constructor(private _name: string) { } | |
| // Factory method with validation rules | |
| static create(name: string): [CityName, Error] { | |
| if (name == null || name.trim().length < CityName.MIN_LEN_NAME || name.trim().length > CityName.MAX_LEN_NAME) { | |
| return [ | |
| null, | |
| new InvalidNameError(name) | |
| ]; | |
| } | |
| // No validation errors | |
| return [new CityName(name), null] | |
| } | |
| get name(): string { return this._name; } | |
| } | |
| // Validation error | |
| class InvalidNameError extends Error { | |
| constructor(name: string) { | |
| super(`The name "${name}" is not valid!`) | |
| } | |
| } | |
| // Input | |
| const text = prompt('Type the city name: '); | |
| // How to use | |
| const [city, error] = CityName.create(text); | |
| if (error != null) { | |
| alert(`Error: ${error.message}`); | |
| } else { | |
| alert(`Welcome to ${city.name}`) | |
| } |
Test on Playground
This approach was used in a clean architecture example, available here
Nice! The pros is that you dont have to define a custom
Resultclass. The downside is that cannot chain errors.