Posted at

Elixirの静的型チェックの確認 - リテラル型

More than 1 year has passed since last update.

結論。

Elixirの静的型チェックで、文字列を指定してすることはできない。

長さぐらいは可能。

同様のことをしたいならatomを使う。

ちゃんと確認してないが、Erlangでも同じだろう。


具体的に

便宜上Flowと比較する。

Flowで以下のような型をElixirで表現するにはどうするか。

// @flow

function sample(hoge_or_goro: "hoge" | "goro") {}

sample("hoge") // Ok
sample("hogehoge") // Error
sample("goro") // Ok

関数sampleは "hoge""goro"という値しか受け取らないようにしたい。

Elixirでは以下のようにするのが良さそう

defmodule Sample do

@spec sample(:hoge | :goro) :: nil
def sample(hoge_or_goro), do: nil

def test(:hoge), do: nil # Ok
def test2(:hogehoge), do: nil # Error
def test3(:goro), do: nil # Ok
def test4(:mogu), do: nil # Error
end

bitstringを使う場合はせいぜい長さを指定するぐらいはできる

defmodule Sample do

@spec sample(<<_::32>) :: nil
def sample(hoge_or_goro), do: nil

def test("hoge"), do: nil # Ok
def test2("hogehoge"), do: nil # Error
def test3("goro"), do: nil # Ok
def test4("mogu"), do: nil # Ok (Errorにしたい)
end

@spec sample(<<"hoge"::32>> :: nilみたいにかきたいがコンパイルできない。


数値リテラル

数値は可能。

まずは、Flowの場合の例

// @flow

function sample(one_or_three: 1 | 3) {}

sample(1) // Ok
sample(2) // Error
sample(3) // Ok
sample(1+2) // Error (Okにしたくはある)

defmodule Sample do

@spec sample(1 | 3) :: nil
def sample(one_or_three), do: nil

def test(), do: hoge(1) # Ok
def test2(), do: hoge(2) # Error
def test3(), do: hoge(3) # Ok
def test4(), do: hoge(1+2) # Ok (やったぜ)
end


参考