キーワード引数をつかっている関数でもキーワードごとに型を指定したい。
指定できるか?
結論。
できるが構造的部分型だったとしてもエラーになる。
キーワードリストでなくて、Mapにしても同様。
なにか良い手はあるかもしれないが思いつかなかった。
確認
便宜上Flowと比較する
// @flow
function sample(hoge_with_goro: {hoge?: number, goro?: number}) {}
sample({}) // Ok
sample({hoge: 1}) // Ok
sample({goro: 2}) // Ok
sample({mogu: 3}) // Ok
sample({hoge: 1, goro: 2}) // Ok
sample({goro: 2, hoge: 1}) // Ok
sample({hoge: 1, mogu: 3}) // Ok
sample({hoge: 1, hoge: 11}) // Ok ({hoge: 11}と同じ)
sample({hoge: 1, goro: 2, mogu: 3}) // Ok
Elixirでやってみる。
defmodule Sample do
@spec sample([hoge: integer, goro: integer]) :: nil
def sample(hoge_with_goro), do: nil
def test(), do: sample([]) # Ok goroもhogeもなくてもOK
def test2(), do: sample(hoge: 1) # Ok goroが足りないのはOK
def test3(), do: sample(goro: 2) # Ok hogeが足りないのはOK
def test4(), do: sample(mogu: 3) # Error 指定してないものがあるとダメ
def test5(), do: sample(hoge: 1, goro: 2) # Ok
def test6(), do: sample(goro: 2, hoge: 1) # Ok 順番は自由
def test7(), do: sample(hoge: 1, mogu: 3) # Error moguがあるからやっぱりだめ
def test8(), do: sample(hoge: 1, hoge: 11) # 複数あっても大丈夫 (JSとはちがって複数値がある)
def test9(), do: sample(hoge: 1, goro: 2, mogu: 3) # Error moguがあるからだめ
end
Mapだとoptionalやrequiredを指定できるので、optionalをつかってみる。
キーワードリストのときと基本的に一緒
defmodule SampleMap do
@spec sample(%{optional(:hoge) => integer, optional(:goro) => integer}) :: nil
def sample(hoge_with_goro), do: nil
def test(), do: sample(%{}) # Ok
def test2(), do: sample(%{hoge: 1}) # Ok
def test3(), do: sample(%{goro: 2}) # Ok
def test4(), do: sample(%{mogu: 3}) # Error
def test5(), do: sample(%{hoge: 1, goro: 2}) # Ok
def test6(), do: sample(%{goro: 2, hoge: 1}) # Ok
def test7(), do: sample(%{hoge: 1, mogu: 3}) # Error
def test8(), do: sample(%{hoge: 1, hoge: 11}) # Ok (%{hoge: 11}になってJSと同じ)
def test9(), do: sample(%{hoge: 1, goro: 2, mogu: 3}) # Error
end