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.

wcl
@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.