# deftype
Define a user-defined type with named fields. Instances are tagged maps.
## Syntax
deftype TypeName %{ field1 %{ :type :string :required true } field2 %{ :type :number :default 0 } } deftype Child << Parent %{ extra-field %{} }
## Examples
deftype Point %{ x %{} y %{} } set p [Point 10 20] echo $p~x # 10 echo $p~y # 20 echo [type $p] # Point
deftype Person %{ name %{ :type :string :required true } age %{ :type :number :required true } email %{ :type :string } } set alice [Person "Alice" 30 "alice@example.com"]
# Type inheritance deftype Point3D << Point %{ z %{} } set p [Point3D 1 2 3] echo $p~x # 1 (inherited) echo $p~z # 3
## Field Schema Options
| Option | Type | Description |
|--------|------|-------------|
| `:type` | keyword | `:string`, `:number`, `:boolean`, `:list`, `:map`, or another `deftype` name |
| `:required` | boolean | Field must be present (enforced by strict constructors) |
| `:default` | any | Default value when omitted |
| `:description` | string | Documentation |
| `:many` | boolean | `true` treats the field as repeatable; singles normalize to vectors |
| `:of` | keyword | Element type for `:list`/`:set` fields |
| `:coerce` | boolean | Convert text input (`"8080"` → `8080`, `"true"` → `true`, `"open"` → `:open`) |
| `:min`/`:max` | number | Numeric bounds, or length bounds for strings and collections |
| `:pattern` | string | PCRE2 regex the string must match |
| `:enum`/`:one-of` | vector/set | Allowed values (`:variants` is an alias) |
| `:validate` | function/name | Validator hook; falsy or `%Err` fails |
Rules are enforced by `[Type --field value ...]` kwarg construction,
flag-collection parameters, and `schema/validate` / `schema/from-value`.
Tagged-map literals (`%Type{...}`) and positional construction apply
`:default` only — see Schema.
Inheritance (`<<`) merges field specs key-wise across the whole
chain: a child spec may override `:default` while still inheriting
`:type` from its parent. `info/props` exposes the merged view as
`:effective-schema`.
## Notes
- Access fields with tilde: `$instance~field`
- Optional field access: `$instance~?field` (returns nil if missing)
- Instances are also maps: `[is? "map" $p]` is true
- Tagged map literal: `%Point{ x 10 y 20 }`
- `is?`, `^Type` match patterns, and field checks walk the full parent chain
## See Also
`defunion`, `defprotocol`, `defimpl`, `defmethod`, `type`, `is?`,
`schema/validate`, `schema/from-value`