Skip to main content
Not every class can implement Validatable: it may come from a library, be generated, or have its rules in another module. validation<T> { } writes the rules of a type from outside it, and returns a Validation<T> that checks any value of that type.
Address.kt
Inside the block, the value being checked is this, so ::street is its property and country its value, exactly as inside a Validatable. The constraints are the same, and so is the result.

Validating a value

Validation<T> takes the value to check:
The zip code is not checked here: postalCode knows the formats of 72 countries by their alpha-2 code, and USA is not one of them, so it has nothing to compare against.

Validating a property with these rules

A property of that type is checked with valid(rules), and its violations are nested under the property:
Delivery.kt

One value, once

When you have a single value and do not need to reuse the rules, validatable(value) { } pairs the value with its rules and returns a Validatable, with all four ways to run it:

Rules as an extension

The block that Validatable uses, validation { }, also works in an extension, which is another way to keep the rules of a foreign class next to your code. The extension is then passed to valid as a function reference:

Which one to pick

Implement Validatable. The rules travel with the class, and valid() needs no argument.
Write a Validation<T> with validation<T> { }, one per set of rules, such as addressForShipping and addressForBilling, and pass the one you need to valid(...).
Implement ContextualValidatable<C>: the caller passes the context, such as the logged-in customer.