gradient
gradient copied to clipboard
t() issues with struct!/2
Code:
@type t :: %__MODULE__{
..fields here
}
@doc false
@spec new(map) :: t()
def new(params) do
struct!(__MODULE__, params)
end
Error
The function call on line 44 is expected to have type t() but it has type struct()
42 @spec new(map) :: t()
43 def new(params) do
44 struct!(__MODULE__, params)
45 end
46 end
Hey, Alan!
This requires an explicit downcast, since not every struct()
is a valid t()
. You know this particular one is, but the typechecker doesn't. That's where Gradient.TypeAnnotation
comes in handy:
defmodule TestStruct do
use Gradient.TypeAnnotation
defstruct f: "some value"
@type t :: %__MODULE__{
:f => String.t()
}
@doc false
@spec new(map) :: t()
def new(params) do
struct!(__MODULE__, params) |> assert_type(t())
end
end
That way struct!/2
does the runtime check that params
are valid for this particular struct, whereas assert_type(_, t())
let's the typechecker know that from now on it's not a general struct()
type instance, but a proper t()
instance.