-1

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

4

1 回答 1

1

虽然很难判断是否错误,或者您的代码是否存在导致此问题的故障,但在传递给此函数之前没有看到上下文是如何构建的,但有一些一般性建议。

在各处使用深度模式匹配来缩小问题范围。

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

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

于 2021-06-25T09:19:04.957 回答