Elixir 是一種動態型別語言,這表示它不提供編譯時期的型別檢查。儘管如此,型別規格仍然很有用,因為它們:
你可以在函式定義之前,使用 @spec 模組屬性為函式加上型別規格。
@spec longer_than?(String.t(), non_neg_integer()) :: boolean()
def longer_than?(string, length), do: String.length(string) > length
型別規格中允許的運算式:
基本型別,例如:
boolean()integer()、non_neg_integer()、pos_integer()、float()
list()map()any()型別的聯集:
integer() | list(integer())
參數化型別:
list(integer()):整數的陣列%{age: integer()}:在鍵 :age 下存放整數值的映射遠端型別(定義在某個模組中),例如:
字面值,例如:
%{}:空的映射[]:空的陣列(但 [any()] 是非空的陣列):ok:atom 字面值內建的特殊型別,例如:
char():0..0x10FFFF 範圍內的整數charlist():字元的陣列keyword():由兩元素元組構成的陣列,其中第一個元素是 atom自訂型別
所有型別的完整清單可以在官方文件的「Typespecs」章節中找到。
型別規格中的引數也可以命名,這在區分多個同型別的引數時很有用。
@spec to_hex({hue :: integer, saturation :: integer, lightness :: integer}) :: String.t()
你可以使用以下三種模組屬性的其中一種來定義自訂型別:
@type:定義公開型別@typep:定義私有型別@opaque:定義結構為私有的公開型別@type color :: {hue :: integer, saturation :: integer, lightness :: integer}
@spec to_hex(color()) :: String.t()
String.t() 與 binary() 與 string() 的比較String.t() 是 Elixir 字串應該使用的正確型別,Elixir 字串是 UTF-8 編碼的二進位資料。技術上來說,String.t() 被定義為 binary(),對分析工具而言這兩種型別是等價的,但 String.t() 更能表達意圖,適合用來記錄處理 Elixir 字串的函式。
另一方面,string() 是另一種型別。它是 Erlang 的字串,在 Elixir 中稱為 charlist。在型別規格中應避免使用 string() 型別,改用 charlist()。
Dialyzer 是一種靜態分析工具,可以偵測 Erlang 與 Elixir 程式碼中的型別錯誤等問題。在 Elixir 專案中使用 Dialyzer 最簡單的方式是透過 Dialyxir。