# `Plushie.Type.Composite`
[🔗](https://github.com/plushie-ui/plushie-elixir/blob/v0.7.2/lib/plushie/type/composite.ex#L1)

Behaviour for composite type modules.

Composite types are parameterized by a spec that describes their
inner structure (e.g., the element type for lists, the field specs
for maps). Each composite module implements this behaviour to
handle casting, typespec generation, guards, and display for its
specific parameterization.

Callbacks that recurse into inner types receive a resolver function
from the caller, keeping composite modules decoupled from the type
resolution system.

## Implementations

  - `Plushie.Type.Composite.Enum` - `{:enum, [atoms]}`
  - `Plushie.Type.Composite.List` - `{:list, inner_type}`
  - `Plushie.Type.Composite.Map` - `{:map, {key_type, val_type}}` or `{:map, [name: type]}`
  - `Plushie.Type.Composite.Tuple` - `{:tuple, [types]}`
  - `Plushie.Type.Composite.Union` - `{:union, [types]}`

# `spec`

```elixir
@type spec() :: term()
```

# `cast`

```elixir
@callback cast(spec(), term()) :: {:ok, term()} | :error
```

Casts a user-facing value against the composite spec.

# `castable`
*optional* 

```elixir
@callback castable(spec(), type_resolver :: (term() -&gt; Macro.t())) :: Macro.t()
```

Returns quoted typespec AST for accepted input forms. Defaults to typespec/2.

# `decode`
*optional* 

```elixir
@callback decode(spec(), term()) :: {:ok, term()} | :error
```

Decodes a wire-format value against the composite spec.

# `display_string`

```elixir
@callback display_string(spec(), string_resolver :: (term() -&gt; String.t())) :: String.t()
```

Returns a human-readable type string for documentation.

# `guard`

```elixir
@callback guard(spec(), var :: Macro.t()) :: Macro.t() | nil
```

Returns a quoted guard expression, or nil if no guard applies.

# `typespec`

```elixir
@callback typespec(spec(), type_resolver :: (term() -&gt; Macro.t())) :: Macro.t()
```

Returns quoted typespec AST for the canonical form. The resolver maps inner type refs to their AST.

# `valid_spec?`

```elixir
@callback valid_spec?(spec(), checker :: (term() -&gt; boolean())) :: boolean()
```

Returns true if the spec is structurally valid.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
