# `Sinter.Types`
[🔗](https://github.com/nshkrdotcom/sinter/blob/v0.3.1/lib/sinter/types.ex#L1)

Core type system for Sinter validation.

This module defines the type specifications supported by Sinter and provides
the fundamental validation and coercion functions that power the unified
validation engine.

## Supported Types

* **Primitive Types**: `:string`, `:integer`, `:float`, `:boolean`, `:atom`, `:any`, `:map`
* **Array Types**: `{:array, inner_type}`
* **Union Types**: `{:union, [type1, type2, ...]}`
* **Tuple Types**: `{:tuple, [type1, type2, ...]}`
* **Map Types**: `{:map, key_type, value_type}` or `:map`

## Type Validation

The `validate/3` function is the core validation engine:

    iex> Sinter.Types.validate(:string, "hello", [])
    {:ok, "hello"}

    iex> Sinter.Types.validate(:integer, "not a number", [])
    {:error, [%Sinter.Error{code: :type, ...}]}

## Type Coercion

The `coerce/2` function provides safe type conversion:

    iex> Sinter.Types.coerce(:integer, "42")
    {:ok, 42}

    iex> Sinter.Types.coerce(:integer, "not a number")
    {:error, [%Sinter.Error{code: :coercion, ...}]}

# `composite_type`

```elixir
@type composite_type() ::
  {:array, type_spec()}
  | {:array, type_spec(), keyword()}
  | {:union, [type_spec()]}
  | {:tuple, [type_spec()]}
  | {:map, type_spec(), type_spec()}
  | {:nullable, type_spec()}
  | {:object, Sinter.Schema.t() | [Sinter.Schema.field_spec()]}
  | {:literal, term()}
  | {:discriminated_union, keyword()}
```

# `constraint`

```elixir
@type constraint() ::
  {:min_length, pos_integer()}
  | {:max_length, pos_integer()}
  | {:min_items, non_neg_integer()}
  | {:max_items, pos_integer()}
  | {:gt, number()}
  | {:gteq, number()}
  | {:lt, number()}
  | {:lteq, number()}
  | {:format, Regex.t()}
  | {:choices, [term()]}
```

# `primitive_type`

```elixir
@type primitive_type() ::
  :string
  | :integer
  | :float
  | :boolean
  | :atom
  | :any
  | :map
  | :date
  | :datetime
  | :uuid
  | :null
```

# `type_spec`

```elixir
@type type_spec() :: primitive_type() | composite_type()
```

# `coerce`

```elixir
@spec coerce(type_spec(), term()) :: {:ok, term()} | {:error, [Sinter.Error.t()]}
```

Attempts to coerce a value to the specified type.

Coercion is safe and predictable - it never raises exceptions and only
performs well-defined conversions.

## Parameters

  * `type_spec` - The target type specification
  * `value` - The value to coerce

## Returns

  * `{:ok, coerced_value}` on successful coercion
  * `{:error, [%Sinter.Error{}]}` on coercion failure

## Examples

    iex> Sinter.Types.coerce(:string, :hello)
    {:ok, "hello"}

    iex> Sinter.Types.coerce(:integer, "42")
    {:ok, 42}

    iex> {:error, [error]} = Sinter.Types.coerce(:integer, "not a number")
    iex> error.code
    :coercion

# `to_json_schema`

```elixir
@spec to_json_schema(type_spec()) :: map()
```

Converts a type specification to JSON Schema format.

This function maps Sinter types to their JSON Schema equivalents,
enabling JSON Schema generation for LLM providers.

## Examples

    iex> Sinter.Types.to_json_schema(:string)
    %{"type" => "string"}

    iex> Sinter.Types.to_json_schema({:array, :integer})
    %{"type" => "array", "items" => %{"type" => "integer"}}

# `validate`

```elixir
@spec validate(type_spec(), term(), [atom() | String.t() | integer()]) ::
  {:ok, term()} | {:error, [Sinter.Error.t()]}
```

Validates a value against a type specification.

This is the core validation function that all other validation ultimately uses.
It checks if a value matches the expected type and satisfies any constraints.

## Parameters

  * `type_spec` - The type specification to validate against
  * `value` - The value to validate
  * `path` - The path for error reporting (default: [])

## Returns

  * `{:ok, validated_value}` on success
  * `{:error, [%Sinter.Error{}]}` on validation failure

## Examples

    iex> Sinter.Types.validate(:string, "hello", [])
    {:ok, "hello"}

    iex> Sinter.Types.validate(:integer, 42, [])
    {:ok, 42}

    iex> Sinter.Types.validate({:array, :string}, ["a", "b"], [])
    {:ok, ["a", "b"]}

    iex> {:error, [error]} = Sinter.Types.validate(:string, 123, [])
    iex> error.code
    :type

---

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