Syntax
Here is complete list of predefined validation syntax.
Genericβ
import fields._
import fields.value.FieldsDsl.default._
import fields.FieldPathConversions._
val field: Field[Int] = Field("1", 1)
// field: Field[Int] = Field(path = .1, value = 1)
field.ensure(_ == 3, _.failInvalid.invalid)
// res0: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "must be valid")
// )
field.assert(_ == 3, _.failInvalid)
// res1: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "must be valid")
// )
field.check(f => if(false) f.failMessage("A").invalid else f.failMessage("B").invalid)
// res2: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "B")
// )
field equalTo 2
// res3: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "must be equal to 2")
// )
field notEqualTo 1
// res4: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "must not be equal to 1")
// )
field equalTo Field("2", 2)
// res5: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "must be equal to .2")
// )
field notEqualTo Field("1", 1)
// res6: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "must not be equal to .1")
// )
field in List(2, 3)
// res7: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "must be one of 2,3")
// )
field.all(_ === 2, _ !== 1)
// res8: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "must be equal to 2"),
// ValidationMessage(path = .1, error = "must not be equal to 1")
// )
field.any(_ === 2, _ !== 3)
// res9: RuleK[Sync, Accumulate, ValidationMessage] = List()
field.when(false)(_ !== field.value)
// res10: RuleK[Sync, Accumulate, ValidationMessage] = List()
field.unless(true)(_ !== field.value)
// res11: RuleK[Sync, Accumulate, ValidationMessage] = List()
implicit val policy: Policy[Int] = _ < 0
// policy: Function1[Field[Int], RuleK[Sync, Accumulate, ValidationMessage]] = repl.MdocSession$MdocApp$$Lambda/0x0000007003046cd0@1ae857bf
field.validate
// res12: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .1, error = "must be less than 0")
// )
sealed trait ABC
case class A(a: Int) extends ABC
case class B() extends ABC
case class C() extends ABC
Field[ABC](A(-1)).whenType[A](_.check(_.failMessage("A").invalid))
// res13: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "A")
// )
Field[ABC](A(-1)).whenType[A](_.sub(_.a) > 0)
// res14: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .a, error = "must be greater than 0")
// )
Field[ABC](A(-1)).whenType[B](_.check(_.failMessage("B").invalid))
// res15: RuleK[Sync, Accumulate, ValidationMessage] = List()
Field[ABC](A(-1)).whenType[C](_.check(_.failMessage("B").invalid))
// res16: RuleK[Sync, Accumulate, ValidationMessage] = List()
Booleanβ
Field("false", false).isTrue
// res17: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .false, error = "must be equal to true")
// )
Field("true", true).isFalse
// res18: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .true, error = "must be equal to false")
// )
Orderingβ
import java.time.LocalDateTime
val now = LocalDateTime.now
// now: LocalDateTime = 2026-07-18T23:38:37.276183
val nowF = Field.from(now)
// nowF: Field[LocalDateTime] = Field(path = .now, value = 2026-07-18T23:38:37.276183)
val tomorrow = now.plusDays(1)
// tomorrow: LocalDateTime = 2026-07-19T23:38:37.276183
val yesterday = now.minusDays(1)
// yesterday: LocalDateTime = 2026-07-17T23:38:37.276183
nowF.isBetween(tomorrow, yesterday)
// res19: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(
// path = .now,
// error = "must be greater than or equal to 2026-07-19T23:38:37.276183"
// ),
// ValidationMessage(path = .now, error = "must be less than or equal to 2026-07-17T23:38:37.276183")
// )
nowF < yesterday
// res20: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .now, error = "must be less than 2026-07-17T23:38:37.276183")
// )
nowF <= yesterday
// res21: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .now, error = "must be less than or equal to 2026-07-17T23:38:37.276183")
// )
nowF >= tomorrow
// res22: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(
// path = .now,
// error = "must be greater than or equal to 2026-07-19T23:38:37.276183"
// )
// )
nowF > tomorrow
// res23: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .now, error = "must be greater than 2026-07-19T23:38:37.276183")
// )
Optionβ
Field(None).isDefined
// res24: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must be empty")
// )
val someF: Field[Option[Int]] = Field("a", Some(5))
// someF: Field[Option[Int]] = Field(path = .a, value = Some(5))
someF.isEmpty
// res25: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .a, error = "must not be empty")
// )
someF.some(_ > 10)
// res26: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .a, error = "must be greater than 10")
// )
someOrValid {
for {
option <- someF.option
other <- Field("b", Some(2)).option
} yield option < other
}
// res27: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = .a, error = "must be less than .b")
// )
Stringβ
val stringF: Field[String] = Field("Ann")
// stringF: Field[String] = Field(path = ., value = "Ann")
stringF.startsWith("sca")
// res28: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must start with sca")
// )
stringF.endsWith("la")
// res29: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must end with la")
// )
Field("").nonEmpty
// res30: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must not be empty")
// )
Field("").nonBlank
// res31: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must not be empty")
// )
stringF.minSize(5)
// res32: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must have minimum size of 5")
// )
stringF.maxSize(1)
// res33: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must have maximum size of 1")
// )
stringF.blank
// res34: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must be empty")
// )
stringF.matchesRegex("scala".r)
// res35: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must match scala")
// )
stringF.matches("scala")
// res36: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must match scala")
// )
Iterableβ
val listF: Field[List[Int]] = Field(List(1, 12))
// listF: Field[List[Int]] = Field(path = ., value = List(1, 12))
listF.each(_ > 10)
// res37: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = [0], error = "must be greater than 10")
// )
listF.any(_ === 10)
// res38: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = [0], error = "must be equal to 10"),
// ValidationMessage(path = [1], error = "must be equal to 10")
// )
Field(List()).nonEmpty
// res39: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must not be empty")
// )
listF.minSize(3)
// res40: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must have minimum size of 3")
// )
listF.maxSize(1)
// res41: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must have maximum size of 1")
// )
Mapβ
val mapF: Field[Map[String, Int]] = Field(Map("" -> 2, "2" -> 2))
// mapF: Field[Map[String, Int]] = Field(path = ., value = Map("" -> 2, "2" -> 2))
mapF.minSize(4)
// res42: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must have minimum size of 4")
// )
mapF.maxSize(1)
// res43: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = ., error = "must have maximum size of 1")
// )
mapF.each(_.second > 4)
// res44: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = [], error = "must be greater than 4"),
// ValidationMessage(path = [2], error = "must be greater than 4")
// )
mapF.eachKey(_.nonEmpty)
// res45: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = [], error = "must not be empty")
// )
mapF.eachValue(_ > 4)
// res46: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = [], error = "must be greater than 4"),
// ValidationMessage(path = [2], error = "must be greater than 4")
// )
mapF.any(_.second > 4)
// res47: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = [], error = "must be greater than 4"),
// ValidationMessage(path = [2], error = "must be greater than 4")
// )
mapF.anyKey(_ === "4")
// res48: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = [], error = "must be equal to 4"),
// ValidationMessage(path = [2], error = "must be equal to 4")
// )
mapF.anyValue(_ > 4)
// res49: RuleK[Sync, Accumulate, ValidationMessage] = List(
// ValidationMessage(path = [], error = "must be greater than 4"),
// ValidationMessage(path = [2], error = "must be greater than 4")
// )
Effectfulβ
import zio._
import fields._
import fields.FieldsInteropZIO._
import fields.fail._
import fields.value.FieldsDsl
import fields.error._
object Validation extends FieldsDsl.BaseAccumulate[Task, ValidationError] with ValidationError.failWith.Mixin
import Validation._
def unsafeRun[A](task: Task[A]) = Unsafe.unsafe(implicit unsafe => Runtime.default.unsafe.run(task).getOrThrowFiberFailure())
def isPositiveApi(number: Int): Task[Boolean] = ZIO.from(number > 0)
val field = Field(FieldPath.fromPath("size"), -1)
// field: Field[Int] = Field(path = .size, value = -1)
unsafeRun(field.assertF(isPositiveApi, _.failMessage("API: NOT POSITIVE")).effect)
// res51: List[ValidationError] = List(
// Message(path = .size, error = "API: NOT POSITIVE", message = None)
// )