在这种情况下,Dialyzer 的行为对我来说相当奇怪,我还没有找到任何可以更好地理解它的东西。
这不是错误:
defmodule Blog.UserResolver do
@type one_user :: ( {:error, String.t} )
@spec find(%{id: String.t}, any()) :: one_user
def find(%{id: id}, _info) do
age = :rand.uniform(99)
if (age < 100) do
# This doesn't trigger a type error, even though it's wrong
{:ok, %{email: "dw@1g.io", name: "Deedub"}}
else
{:error, "Age isn't in the right range"}
end
end
end
请注意,绝对可能的返回分支之一与类型签名不匹配。
然而,这确实有一个错误:
defmodule Blog.UserResolver do
@type one_user :: ( {:error, String.t} )
@spec find(%{id: String.t}, any()) :: one_user
# Throws an error since no return path matches the type spec
def find(%{id: id}, _info) do
age = :rand.uniform(99)
if (age < 100) do
{:ok, %{email: "dw@1g.io", name: "Deedub"}}
else
10
end
end
end
在这种情况下,没有任何可能的分支与 typespec 匹配,并且 dialyzer 说有以下错误消息:
web/blog/user_resolver.ex:4: Invalid type specification for function 'Elixir.Blog.UserResolver':find/2. The success typing is (#{'id':=_, _=>_},_) -> 10 | {'ok',#{'email':=<<_:64>>, 'name':=<<_:48>>}}
我不明白的部分是透析器清楚地识别出分支可能返回的两种不同类型((#{'id':=_, _=>_},_) -> 10 | {'ok',#{'email':=<<_:64>>, 'name':=<<_:48>>}
),所以这不是推理的问题。那么为什么它不承认其中一个分支不符合类型规范(如果只有一个分支符合,这似乎很高兴,这根本不是我想要的)