Elixir: Specifying `key_type` for a map, where `key_type` is an enumerated type
我有一个函数返回一个地图,我想为其定义自定义类型。
执行此操作的过程非常简单,除了从以下文档中处理
对于我正在定义的这种新类型,
像
我希望这可以工作:
1 2 3 4 5 6 7 8 | @type home_sharing_rate :: number @type home_sharing_days :: [number] @type home_sharing_booking :: { home_sharing_days, home_sharing_rate } @type income_year ::"2019" |"2020" |"2021" |"2022" |"2023" @type income_month ::"Jan" |"Feb" |"Mar" |"Apr" |"May" |"Jun" |"Jul" |"Aug" |"Sep" |"Oct" |"Nov" |"Dec" @type earned_home_sharing_income_summary :: %{ required(income_year) => %{ required(income_month ) => [home_sharing_booking] } } |
但没有这种运气。但是,我看到Elixir有一些内置类型,例如
TypeScript有很多工具可以实现这一目标,所以我很希望Elixir也能做到。在我看来,不能将类型定义为其值的枚举似乎很奇怪,但是也许Elixir打算使用类型的方式与Typescript不同,而我只是缺少了一些东西。
Typespec仅处理用
1 2 3 4 | defmodule Foo do @typep income_year :: <<"2019"::binary-size(4)>> | <<"2020"::binary-size(4)>> @type earned :: %{ required(income_year) => any() } end |
产生
1 2 3 | ** (CompileError) iex:4: invalid binary specification, expected <<_::size>>, <<_::_*unit>>, or <<_::size, _::_*unit>> with size and unit being non-negative integers |
也就是说,您最多只能求助于
无论您是否希望使用这种类型,我都建议使用防护而不是类型:
1 2 3 4 5 6 7 8 9 | @allowed_years ~w|2019 2020| Enum.each(@allowed_years, fn year -> def do_something(%{unquote(year) => value} = earned) do ... end end) # sink-all clause def do_something(_), do: raise"Year is not allowed." |