在更新我的项目以使用Elixir 1.12后,我注意到Dialyzer抱怨我在某些地方使用点表示法访问了结构的属性。例如,我的应用程序中有一个graphql解析器函数:
def update(_root, %{input: input}, %{context: %{current_user: user}}) do
case user
|> User.update_changeset(input)
|> Repo.update() do
{:ok, updated_user} ->
if user.email !== updated_user.email do
Email.email_changed(user.email, updated_user.email)
|> Mailer.deliver_later()
end
{:ok, updated_user}
err ->
err
end
end
Dialyser突出显示了表达式user.email !== updated_user.email
,并出现以下错误:
The call _.'email'/() requires that _@1 is of type atom(), not {map(), map()}
知道这个错误意味着什么以及如何修复它吗?
(这一切编译和运行都很好,我只是想知道为什么它似乎不能满足Dialyzer(
虽然很难判断透析器是否错误,或者您的代码出现了导致此问题的小故障,但在传递给此函数之前,如果不了解上下文是如何构建的,则有一些一般建议。
处处使用深度模式匹配来缩小问题范围。
def update(_root, %{input: input},
%{context: %{current_user: %User{email: email}}}) do
user
|> User.update_changeset(input)
|> Repo.update()
|> case do
{:ok, %User{email: ^email} = user} ->
{:ok, user}
{:ok, %User{email: updated_email} = user} ->
email
|> Email.email_changed(updated_email)
|> Mailer.deliver_later()
{:ok, user}
err ->
err
end
end
这样代码就更干净了,意图也更清晰了,错误(如果发生(也更明显了,并粘在了它实际属于的地方。