Typed Elixir

Given this module:

    defmodulet TypedTest do
      @moduledoc false

      import String

      @type test_type :: String.t

      @spec simple() :: nil
      def simple(), do: nil

      @spec hello(String.t) :: String.t | Map.t
      def hello(str) when is_binary(str) do
        # @spec ret :: String.t # TODO
        ret = trim(str) <> " world"
        ret
      end

      def fun_no_spec(), do: nil
    end

So far it just tests if specs exist, but it is a start. Verbosely it prints out this at compile-time:

Type Checking: TypedElixirTest.TypedTest

Types:
%{test_type: {{:., [line: 19],
    [{:__aliases__, [counter: 0, line: 19], [:String]}, :t]}, [line: 19], []}}

Specs:
%{{:hello,
   1} => {[{{:., [line: 24],
      [{:__aliases__, [counter: 0, line: 24], [:String]}, :t]}, [line: 24],
     []}],
   {:|, [line: 24],
    [{{:., [line: 24], [{:__aliases__, [counter: 0, line: 24], [:String]}, :t]},
      [line: 24], []},
     {{:., [line: 24], [{:__aliases__, [counter: 0, line: 24], [:Map]}, :t]},
      [line: 24], []}]}}, {:simple, 0} => {[], nil}}

Funs:
%{{:fun_no_spec, 0} => {{:fun_no_spec, [line: 31], []}, [do: nil]},
  {:hello,
   1} => {{:when, [line: 25],
    [{:hello, [line: 25], [{:str, [line: 25], nil}]},
     {:is_binary, [line: 25], [{:str, [line: 25], nil}]}]},
   [do: {:__block__, [line: 12],
     [{:=, [line: 27],
       [{:ret, [line: 27], nil},
        {:<>, [line: 27],
         [{:trim, [line: 27], [{:str, [line: 27], nil}]}, " world"]}]},
      {:ret, [line: 28], nil}]}]},
  {:simple, 0} => {{:simple, [line: 22], []}, [do: nil]}}

Funs missing specs:
[{{:fun_no_spec, 0}, {{:fun_no_spec, [line: 31], []}, [do: nil]}}]

Finished in 0.09 seconds

I wonder if @types can have arguments to make them parameterized… if not I should support that if possible or make a new one… I do not have too much time to work on this but at least it is a start if I confine my code to a certain style…

1 Like