# `PtcRunner.SubAgent.Signature.TypeResolver`
[🔗](https://github.com/andreasronge/ptc_runner/blob/main/lib/ptc_runner/sub_agent/signature/type_resolver.ex#L1)

Resolve paths against parsed signature types.

Given a parsed signature and a path (like ["items", "name"]), determines the expected
type at that path. Used for validating section fields in Mustache templates.

# `iterable_type?`

```elixir
@spec iterable_type?(term()) :: boolean()
```

Check if a type is iterable (can be used with {{#section}}).

## Examples

    iex> PtcRunner.SubAgent.Signature.TypeResolver.iterable_type?({:list, :string})
    true

    iex> PtcRunner.SubAgent.Signature.TypeResolver.iterable_type?(:string)
    false

    iex> PtcRunner.SubAgent.Signature.TypeResolver.iterable_type?({:map, [{"x", :int}]})
    true

# `list_element_type`

```elixir
@spec list_element_type({:signature, list(), term()}, String.t()) ::
  {:ok, term()} | {:error, term()}
```

Get the element type for a list parameter.

Returns `{:ok, element_type}` if the parameter is a list, or `{:error, reason}` if not.

## Examples

    iex> sig = {:signature, [{"items", {:list, {:map, [{"name", :string}]}}}], :any}
    iex> PtcRunner.SubAgent.Signature.TypeResolver.list_element_type(sig, "items")
    {:ok, {:map, [{"name", :string}]}}

    iex> sig = {:signature, [{"tags", {:list, :string}}], :any}
    iex> PtcRunner.SubAgent.Signature.TypeResolver.list_element_type(sig, "tags")
    {:ok, :string}

    iex> sig = {:signature, [{"name", :string}], :any}
    iex> PtcRunner.SubAgent.Signature.TypeResolver.list_element_type(sig, "name")
    {:error, {:not_a_list, :string}}

# `map_fields`

```elixir
@spec map_fields(term()) :: {:ok, list()} | {:error, term()}
```

Get the fields of a map type.

Returns `{:ok, fields}` where fields is a list of `{name, type}` tuples,
or `{:error, reason}` if the type is not a map.

## Examples

    iex> PtcRunner.SubAgent.Signature.TypeResolver.map_fields({:map, [{"name", :string}, {"age", :int}]})
    {:ok, [{"name", :string}, {"age", :int}]}

    iex> PtcRunner.SubAgent.Signature.TypeResolver.map_fields(:string)
    {:error, {:not_a_map, :string}}

# `resolve_path`

```elixir
@spec resolve_path({:signature, list(), term()}, [String.t()]) ::
  {:ok, term()} | {:error, term()}
```

Resolve a path to its expected type from a parsed signature.

Returns `{:ok, type}` if the path is valid, or `{:error, reason}` if not.

## Examples

    iex> sig = {:signature, [{"user", :string}], {:map, [{"result", :int}]}}
    iex> PtcRunner.SubAgent.Signature.TypeResolver.resolve_path(sig, ["user"])
    {:ok, :string}

    iex> sig = {:signature, [{"items", {:list, {:map, [{"name", :string}]}}}], :any}
    iex> PtcRunner.SubAgent.Signature.TypeResolver.resolve_path(sig, ["items"])
    {:ok, {:list, {:map, [{"name", :string}]}}}

# `scalar_type?`

```elixir
@spec scalar_type?(term()) :: boolean()
```

Check if a type is a scalar (can be used with {{.}} in sections).

## Examples

    iex> PtcRunner.SubAgent.Signature.TypeResolver.scalar_type?(:string)
    true

    iex> PtcRunner.SubAgent.Signature.TypeResolver.scalar_type?({:map, [{"x", :int}]})
    false

    iex> PtcRunner.SubAgent.Signature.TypeResolver.scalar_type?({:list, :string})
    false

---

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