型仕

型仕様 の Elixir

1個の演習

型仕様について

Elixirは動的型付け言語なので、コンパイル時の型チェックは提供されていません。それでも型仕様は役に立ちます。型仕様には次のような役割があるからです。

  • ドキュメントとしての役割を果たします。
  • Dialyzerのような静的解析ツールが、潜在的なバグを見つけるために利用できます。

型仕様は、関数定義の直前に@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 - アトムリテラル
  • 組み込みの特殊型、例えば:

    • char() - 0..0x10FFFFの範囲の整数
    • charlist() - 文字の配列
    • keyword() - 最初の要素がアトムである2要素のタプルの配列
  • カスタム型

すべての型の完全なリストは、公式ドキュメントの「Typespecs」セクションにあります。

引数に名前を付ける

型仕様の引数には名前を付けることもできます。これは同じ型の引数が複数あるときに区別するのに便利です。

@spec to_hex({hue :: integer, saturation :: integer, lightness :: integer}) :: String.t()

カスタム型

カスタム型は、次の3つのモジュール属性のいずれかを使って定義できます。

  • @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()として定義されており、解析ツールにとってこの2つの型は同等ですが、Elixirの文字列を扱う関数をドキュメント化するには、String.t()の方が意図が伝わりやすい選択です。

一方、string()は別の型です。これはErlangの文字列で、Elixirでは文字リストとして知られています。型仕様ではstring()型を避け、代わりにcharlist()を使うべきです。

Dialyzer

Dialyzerは、ErlangやElixirのコードにおける型エラーなどの問題を検出できる静的解析ツールです。ElixirプロジェクトでDialyzerを使う最も簡単な方法は、Dialyxirを使うことです。

GitHubで編集 リンクは新しいウィンドウまたはタブで開きます

型仕様を学習する