Qqwy / elixir-type_check

TypeCheck: Fast and flexible runtime type-checking for your Elixir projects.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support finding spec definitions & checking types based on behaviours

japhib opened this issue · comments

A common pattern in Elixir is to define a function spec in a behaviour via a @callback attribute, and then modules implementing that behaviour put @impl true on the implementing functions rather than reproducing the full spec.

It would be awesome if TypeCheck could work with these attributes to generate runtime type checks the same way it does for @spec! and @type!. E.g. replace the attributes with probably something like @behaviour! and @callback!, and generate runtime checks for functions with @impl!.

Ideally this feature would allow for handling behaviours defined without TypeCheck. I'm guessing that would happen in a similar way to the existing overrides functionality, but probably would need some tweaks to play nicely with the callback logic.

Hypothetical example:

defmodule MyBehaviour do
  use TypeCheck
  @callback! my_func(integer(), atom()) :: :ok | {:error, integer()}
end

defmodule MyModule do
  use TypeCheck
  @behaviour! MyBehaviour

  @impl! true
  # Gets a runtime-generated type check as if it had the spec from the callback, e.g.
  # @spec! my_func(integer(), atom()) :: :ok | {:error, integer()}
  def my_func(the_integer, the_atom) do
    :ok
  end
end

Hi there!

This is a great suggestion. I'm not sure yet how it could be implemented (but I'll give it some thought).
For now, I first want to focus on finishing the basic functionality first (which mainly means: ensuring that all common typespec map syntaxes are properly supported).

However, this definitely is a cool suggestion for the future!

💚

@orsinium This might be the prime example of something which we can support using the spec parser.

That way, we could use it without having to add TypeCheck to the Behaviour's own module at all (and e.g. use it to check custom implementations for pre-existing behaviours).

@impl! true / @impl! SomeBehaviourName could then invoke, once the next function is defined, the parser's lookup/convert functionality to wrap the implementation using the spec from the behaviour module.

What do you think?

Closing this for now.

I still think it is an interesting idea, but I believe it might be better as an extra library rather than adding this logic to the core library necessarily. This will keep the core library simpler and more focused.