使用点语法访问 struct prop 时出现 Elixir Dialyzer 错误

Elixir Dialyzer error when accessing struct prop using dot syntax

更新我的项目以使用 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

这样代码更清晰,意图更清晰,错误(如果发生)更明显并粘在它实际所属的地方。