# 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`