How to correctly handle assigns in LiveView Sigil without getting Dialyzer warnings?


It seems that any LiveView sigil is expected to have in its scope an assigns map.
So not a keyword list or anything else, but a map.

But often I end up with a Dialyzer error (or warning) that The pattern can never match the type

Consider the following simple example for a helper:

defp product_link(product) do
  assigns = %{name:, url: product.url}

  <a href="<%= @url %>">
    <%= @name %>

And calling simply like that:

<%= product_link(product) %>

With ElixirLS Dialyzer, I got the following warning/error:

The pattern can never match the type.

%{:__changed__ => _}

%{:name => _, :url => _}

Now if instead I do the following, I don’t get the error but it’s more verbose on the calling side (particularly bothering when I have a list with more than two keywords pair).

defp product_link(assigns) do
  assigns = Enum.into(assigns, %{})

  <a href="<%= @url %>">
    <%= @name %>

And calling like that:

<%= product_link(name:, url: product.url) %>

But in this case I don’t get any warning/error.

So I wanted to know first, what exactly is the meaning of that warning?
Where does it come from?

Is it possible to fix it?
I’m not using any spec, but does defining some specs could prevent this error? (Though, it’s a private function so I’m not sure for that).

If not, how to disable only that warning/error here?

I didn’t defined anything particular to use Dialyzer, but it came for free with ElixrLS in VSCode. So in the meantime to learn more about specs, I rather want to stick with this default usage and try to get no warnings/errors.

And lastly, besides the Dialyzer warning, what is the best way to handle the assigns in LiveView sigils?

Thank you very much folks!

Well I found a way to mix both versions, ie. having a simpler call while not having any error.
Simply build the keyword list in the function like so:

defp product_link(product) do
  assigns =
    [name:, url: product.url] 
    |> Enum.into(%{})

  <a href="<%= @url %>">
    <%= @name %>

But I don’t know if it’s a valid workaround and if it’s correct idiomatic Elixir.
Also, while doing this I don’t know at all why this is needed…

Any thought are welcome…


Hello everybody…
I’m coming back to this topic…
The following is obviously correct and match to:

%{name: "my product"} = [name: "my product"] |> Enum.into(%{})

But why using the left hand side in a liveview template brings the mentioned error while using the right hand side doesn’t bring any error?

I hope I’ll receive some answer this time :wink:

You can remove the warning by using…

assigns = %{__changed__: nil, name:, url: product.url}

I guess it needs this key.

1 Like

Indeed, this way the warning disappears.
But it seems weird to add that key out of context…

But for a better understanding…
How people are managing this case?
But maybe it is not a commonly used pattern (though it seems common enough to me) particularly when trying to “componentize” UI parts…

Is it possible to rather disable that very warning?
If so, could that cause some side effect else where?

Thank you very much BTW…