5. Declaring types and decorators
Turn record types into an authoring vocabulary with @block, @inline, and @default.
After this lesson you can
- Declare a nestable block kind with @block("kind") - Bind block labels to fields with @inline(slot) - Fill omitted fields with @default(expr)
Before you start: Lists, records, and pipe-tables
Decorators are prefix annotations that turn a plain record type into schema. @block("service") makes the type authorable as service ... { ... } blocks; @inline(0) says the first label lands in that field; @default(80) supplies a value when the author omits the field, so common cases stay terse.
The pattern to internalise: the type declaration is the *vocabulary*, the block instances are the *content*. Constraints (@min, @max, @non_empty) and type aliases layer onto the same declarations as your model grows.
§ 1Exercise: Design a block kind
Declare a service block with a labelled name and a defaulted port, author two instances, and confirm the default applies.
@block("service")
type Service {
@inline(0) name: utf8
@default(80) port: u32
region: utf8
}
@document
type Config {
@children("service") services: list<Service>
}
service "web" { region = "us-east-1" }
service "api" { port = 9090u32 region = "eu-west-1" }
Expected result
wcl check prints OK, and wcl eval config.wcl services.web.port prints 80 — the default filled the omitted field.
Hint
Remove @default(80) and the web instance stops validating: without a default, port is required.