I am looking for a good way to validate freezed models. So far I came up with three approaches, which are shown in the snippet below.
@freezed
class Options with _$Options {
Options._();
factory Options._internal({required List<String> languages}) = _Options;
// #1: validation in factory constructor
factory Options({required List<String> languages}) {
if (languages.isEmpty) {
throw Exception('There must be at least one language.');
}
return Options._internal(languages: languages);
}
// #2: expose mutation methods with built-in validation
Options changeLanguages(List<String> languages) {
if (languages.isEmpty) {
throw Exception('There must be at least one language.');
}
return copyWith(languages: languages);
}
// #3: validation using custom properties
late final List<Exception> validationResult = <Exception>[
if (languages.isEmpty) Exception('There must be at least one language.'),
];
// #4: validation using a custom method
void validate() {
if (languages.isEmpty) {
throw Exception('There must be at least one language.');
}
}
}
#1: Validation inside a factory constructor. Unfortunately, this only works for newly created objects and requires further changes for copyWith
.
#2: Validation inside a mutation method. This could be used in addition to #1 to run validation after object creation, but still does not work for copyWith
.
#3: Exposing a property with validation errors. So far, this is my favorite approach, even though it requires users of the model to explicitly look for errors.
#4: A variation of #3, which uses a throwing method instead of providing a list of errors.
What are your thoughts on this? Do you know any better approaches or is there a part of the package API, which I have overlooked?