I know I put the cart before the horse, but AI providers started this race, not me.
Welcome Typle, the library that leverages a modern Elixir type system to discover types given the bunch of Elixir code.
The real application is my credo add-ons. In our team there are people who sometimes get lazy and use Access everywhere like: container[:key] no matter what container is. Also there are assistants who always use Access, because container.key is less fancy, or who knows why. I personally find this quite disturbing. Let alone Access is slower, it absolutely does not belong here.
So I started to implement a credo check for that, and I realized I should issue a warning if and only if the container is a map (and a key is an atom literal, but that’s a no-brainer.)
That’s how Typle was born. It’s just a baby-lib, but it might be already quite useful for those linting their code.
iex|🌢|1 ▶ {:ok, type} = Typle.Inference.infer_file("test/support/sample_module.ex")
{:ok,
%{
exprs: %{
{6, 11} => "a",
{6, 14} => "b",
{7, 5} => "a",
{7, 7} => ":erlang.+(a, b)",
{7, 9} => "b",
{10, 13} => "name",
{11, 0} => "<<\"Hello, \", name::binary>>",
{14, 19} => "input",
{15, 5} => "case Integer.parse(input) do\n {num, _rest} -> {:ok, num}\n :error -> {:error, :invalid}\nend",
{15, 17} => "Integer.parse(input)",
{15, 24} => "input",
{16, 8} => "num",
{16, 13} => "_rest",
{16, 29} => "num",
{21, 22} => "x",
{21, 30} => "x",
{22, 16} => "x",
{22, 24} => "x"
},
types: %{
{6, 11} => #Typle.Type<dynamic()>,
{6, 14} => #Typle.Type<dynamic()>,
{7, 5} => #Typle.Type<integer()>,
{7, 7} => #Typle.Type<dynamic(float() or integer())>,
{7, 9} => #Typle.Type<integer()>,
{10, 13} => #Typle.Type<dynamic()>,
{11, 0} => #Typle.Type<binary()>,
{14, 19} => #Typle.Type<dynamic()>,
{15, 5} => #Typle.Type<{:error, :invalid} or {:ok, dynamic(integer())}>,
{15, 17} => #Typle.Type<dynamic(:error or {integer(), binary()})>,
{15, 24} => #Typle.Type<dynamic()>,
{16, 8} => #Typle.Type<dynamic(integer())>,
{16, 13} => #Typle.Type<dynamic(binary())>,
{16, 29} => #Typle.Type<dynamic(integer())>,
...
}
}}
mix tasks included.
Enjoy!






















