# TypeCounselor
An experimental library for suggesting type specifications based on Elixir maps
and structures.
```elixir
iex> map_1 = %{identifier: "IBM5100"}
iex> map_2 = %{identifier: 5100}
iex> TypeCounselor.suggest([map_1, map_2])
"%{identifier => String.t() | :non_neg_integer}"
```
## Usage
### 1. Installation
Add the package to your `mix.exs`:
```elixir
def deps do
[
{:type_counselor, "~> 0.1.0", only: :test}
]
end
```
### 2. Instrument the codebase
Manually instrument places where structs are created to call `TypeCounselor.add/2`.
Example:
```elixir
def populate_users(user_ids) do
Enum.map(user_ids, fn user_id ->
case SpotifyClient.fetch_user(user_id) do
{:ok, user_info} ->
# Note the `TypeCounselor.add/2` call below
TypeCounselor.add(:user, %User{
name: user_info[:username],
profile: user_info[:profile_url],
flags: user_info[:flags]
})
{:error, _} = result ->
result
end
end)
end
```
### 3. Run tests and collect type suggestions
```shell
# Run tests and spawns iex for collecting type suggestions
$ iex -S mix test
Erlang/OTP 25 [erts-13.0.3] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]
Compiling 5 files (.ex)
Generated type_counselor app
.......
Finished in 0.01 seconds (0.01s async, 0.00s sync)
7 tests, 0 failures
```
After tests are run, `iex` should be spawned:
```elixir
iex> suggestions = TypeCounselor.fetch(:user)
iex> File.write!("user.exs", suggestions)
```
The content of the created `user.exs` will contain type suggestions for `user`
according to `user_info` content values during test runtime:
```elixir
%{
name => String.t() | nil,
profile => String.t(),
flags => list(:enabled | :disabled)
}
```