# `CEL.Type`
[🔗](https://github.com/hansihe/pb_ex/blob/v0.2.0/cel_ex/lib/cel/type.ex#L1)

CEL types, in the shorthand `CEL` uses wherever it takes or returns a
type: variable declarations in `CEL.Env.build/1`, overload signatures in
`CEL.Function.Overload`, and the types of `CEL.Expr` nodes and
`CEL.Checked.type/2`.

  * `:bool`, `:int`, `:uint`, `:double`, `:string`, `:bytes`
  * `:timestamp` and `:duration` — `google.protobuf.Timestamp` and
    `google.protobuf.Duration`
  * `:null` and `:dyn`
  * `{:list, t}` and `{:map, key, value}`
  * `{:message, name}` — a message type, by its `CEL.TypeProvider`'s
    name for it, such as `:"pkg.Message"`. A declaration may spell it as an
    atom or a string; types CEL returns carry the provider's form.
  * `{:enum, name}` — an enum type, named the same way
  * `{:wrapper, primitive}` — a wrapper message such as
    `google.protobuf.Int64Value` (`{:wrapper, :int}`)
  * `{:optional, t}` — `optional_type(t)`
  * `{:type, t}` — the type of a type value; `:type` alone is
    `{:type, :dyn}` when declaring
  * `{:abstract, name, params}` — any other parameterised type

# `primitive`

```elixir
@type primitive() :: :bool | :int | :uint | :double | :string | :bytes
```

# `t`

```elixir
@type t() ::
  :dyn
  | :null
  | primitive()
  | :timestamp
  | :duration
  | {:wrapper, primitive()}
  | {:type, t()}
  | {:list, t()}
  | {:map, t(), t()}
  | {:message, CEL.TypeProvider.name()}
  | {:enum, CEL.TypeProvider.name()}
  | {:optional, t()}
  | {:abstract, String.t(), [t()]}
```

# `format`

```elixir
@spec format(t()) :: String.t()
```

Spells a type as CEL does, for messages to users.

    iex> CEL.Type.format({:map, :string, {:list, :int}})
    "map(string, list(int))"

    iex> CEL.Type.format(:timestamp)
    "google.protobuf.Timestamp"

---

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