Posted at

Elixirの静的型チェックの確認 - キーワードリストをつかった引数

More than 1 year has passed since last update.

キーワード引数をつかっている関数でもキーワードごとに型を指定したい。

指定できるか?

結論。

できるが構造的部分型だったとしてもエラーになる。

キーワードリストでなくて、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


参考


関連