Skip to content

Instantly share code, notes, and snippets.

@apboobalan
Created September 4, 2020 09:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apboobalan/464aa45b2ad63790aa2473c6f357b791 to your computer and use it in GitHub Desktop.
Save apboobalan/464aa45b2ad63790aa2473c6f357b791 to your computer and use it in GitHub Desktop.
Gist about typespecs in Elixir
  • To define type spec for a functions @spec function_name(arg_1_type, arg_2_type) :: return_type
  • To define new type@type new_type_name :: existing_type
  • To document type place @typedoc """ description """ above type definition.
  • We can create product types such as lists, tuples and maps using their own syntax with members being the types.
  • Eg. Product types
@type statuses :: [atom]

@type number_with_remark :: {number, String.t}

@type error_map :: %{
	message: String.t,
	line_number: integer
}
  • We can create sum types like ok tuple and error tuple using |
  • Eg. Sum types
@type parse_response :: {:ok, term} | {:error, String.t}
  • Custom types are exported along with the module. so we can use them in other modules using Module_name.custom_type
  • To make a custom type and its documentation private use @typep instead.
  • Type specs also help in defining behaviour
  • The functions that need to be implemented by the behavior are specified as @callback function_name(arg_1_type, arg_2_type) :: return_type
  • Eventhough string is a primitive type in Elixir, we should use String.t() instead. string represents erlang string which is implemented as char_list.
  • String.t() represents Elixir string implementation which can also be referred as binary,
  • More info about basic types.
  • More info about Literals
  • Short hand to represent above types.
  • If we want to create map with dynamic keys and values. %{optional(any) => any}
  • An opaque type, defined with @opaque is a type where the internal structure of the type will not be visible, but the type is still public.
  • Types can be parameterized by defining variables as parameters; these variables can then be used to define the type.@type dict(key, value) :: [{key, value}]. When using dict(atom, integer | String.t()).
  • Guards can be used to restrict type variables given as arguments to the function. @spec function(arg1, arg2) :: {arg1, arg2} when arg1: atom, arg2: integer
  • Type variables with no restriction can also be defined using var.@spec function(arg) :: [arg] when arg: var
  • We can inline types as
@spec days_since_epoch(year :: integer, month :: integer, day :: integer) :: integer
@type color :: {red :: integer, green :: integer, blue :: integer}
  • @macrocallback used to declare marcros inside behaviour.
  • @optional_callbacks non_vital_fun: 0, non_vital_macro: 1 related to behaviour, to define optional callback functions.
  • To know about behaviour details
MyBehaviour.behaviour_info(:callbacks)
#=> [vital_fun: 0, "MACRO-non_vital_macro": 2, non_vital_fun: 0]
MyBehaviour.behaviour_info(:optional_callbacks)
#=> ["MACRO-non_vital_macro": 2, non_vital_fun: 0]
  • floor_div(integer(), neg_integer() | pos_integer()) :: integer() Note that 0 is omitted by neg_interger | pos_integer.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment