ValidationError
The ValidationError type provides a generic error type for input validation. Useful for form validation, configuration validation, API input validation, and any scenario requiring structured validation feedback.
import IO
validate-email = fn(email) =>
if not (String.contains? email "@") then
Err InvalidValue{field: "email", value: email, reason: "missing @"}
else
Ok email
See Also: Contracts
For preventing errors through preconditions and postconditions, see
Contracts. Use @pre
to validate inputs before operations that might fail.
Constructors
ValidationError
type ValidationError = InvalidValue{...} | MissingField{...} | ...
| Constructor | Fields | Description |
|---|---|---|
InvalidValue |
field: String, value: String, reason: String |
A field has an invalid value |
MissingField |
field: String |
A required field is missing |
OutOfRange |
field: String, value: String, min: String, max: String |
A value is outside the allowed range |
PatternMismatch |
field: String, value: String, pattern: String |
A value doesn't match the expected pattern |
ValidationError |
message: String |
Generic validation error |
Trait Implementations
Show
Provides human-readable error descriptions:
err = InvalidValue{field: "age", value: "-5", reason: "must be positive"}
println (show err)
# => InvalidValue: age='-5' (must be positive)
err = MissingField{field: "email"}
println (show err)
# => MissingField: email
Error
Implements the standard Error trait with message and kind:
| Constructor | Error Kind |
|---|---|
InvalidValue | :invalid-value |
MissingField | :missing-field |
OutOfRange | :out-of-range |
PatternMismatch | :pattern-mismatch |
ValidationError | :validation-error |
Examples
Form Validation
type UserForm = {
name: String,
email: String,
age: String
}
validate-user = fn(form) =>
errors = []
# Validate name
errors = if String.is-empty? form.name then
errors ++ [MissingField{field: "name"}]
else
errors
# Validate email
errors = if not (String.contains? form.email "@") then
errors ++ [InvalidValue{
field: "email",
value: form.email,
reason: "must contain @"
}]
else
errors
# Validate age
errors = match Int.parse form.age
| Ok n if n < 0 || n > 150 ->
errors ++ [OutOfRange{
field: "age",
value: form.age,
min: "0",
max: "150"
}]
| Err _ ->
errors ++ [InvalidValue{
field: "age",
value: form.age,
reason: "must be a number"
}]
| _ -> errors
if empty? errors then Ok form else Err errors
Pattern Validation
validate-phone = fn(phone) =>
pattern = "###-###-####"
if String.matches? phone "^[0-9]{3}-[0-9]{3}-[0-9]{4}$" then
Ok phone
else
Err PatternMismatch{
field: "phone",
value: phone,
pattern: pattern
}
Collecting All Errors
# Collect all validation errors instead of failing fast
validate-all = fn(validations) =>
errors = validations
|> filter (fn(r) => Result.is-err? r)
|> map Result.unwrap-err
if empty? errors then
Ok ()
else
Err errors