Optional values are a pervasive programming pattern in OCaml. Since Michelson and LIGO are both inspired by OCaml, optional types are available in LIGO as well. Similarly, OCaml features a unit type, and LIGO features it as well. Both the option type and the unit type are instances of a more general kind of types: variant types.
The unit Type
unit type in Michelson or LIGO is a predefined type that
contains only one value that carries no information. It is used when
no relevant information is required or produced. Here is how it used.
In JsLIGO, the unique value of the
unit type is
. The global variable
 so that name can be used for clarity, but the value is the same.
Discriminated union type
The simplest form of pattern matching in JsLIGO is with the help of a discriminated union type, which should be familiar for developers coming from TypeScript.
kind field is unique among the objects. If not, an error will be
generated. Also, if multiple fields are present which can be used as unique
field, only the first unique field will be used.
Creating an object from a discriminated union type requires all the fields to be fully written. So for increment that would be:
Pattern matching over a discriminated union type works like this:
Note that all cases of the discriminated union must be handled, if not an error will be generated.
These "strict" rules on discriminated union types help prevent bugs where cases are not handled correctly.
Here is how we define a coin as being either head or tail (and nothing else):
Tail in the definition of the type
called data constructors, or variants. In this particular, they
carry no information beyond their names, so they are called constant
In general, it is interesting for variants to carry some information, and thus go beyond enumerated types. In the following, we show how to define different kinds of users of a system.
In JsLIGO, a constant constructor is equivalent to the same constructor
taking an argument of type
unit, so, for example,
Guest () is the
same value as
There are cases where several sum types match a given constructor.
In the example below, types
t6 are all possible types for
In this case, the compiler will choose one of these types as the type of the expression, and throw a warning stating that other types are possible.
You can add a type annotation to remove this ambiguity.
NOTE : The compiler will choose in priority the latest matching
sum type in the current scope, if no type is defined in this scope, it
will look in the latest module, if not in the second latest etc.
Below, it will choose
t1, and if
t1 didn't match it would have
option type is a predefined variant type that is used to express
whether there is a value of some type or none. This is especially
useful when calling a partial function, that is, a function that is
not defined for some inputs. In that case, the value of the
type would be
Some (v), where
v is some
meaningful value of any type. An example in arithmetic is the
You can extract the value of a
Some (v) with the function
Option.unopt (Some (v)). In case the value is
None, this will fail with an error.
The proper way to deal with optional values is by means of pattern matching.
Pattern matching is similar to the
switch construct in
on the value of a variant, record, tuple, or list.
A component of a pattern can be discarded by using a wildcard
instead of a variable name.
LIGO will warn about unused variables bound in patterns in the same
way that function arguments are warned about. Variable names beginning
_ can be used as a binder to prevent warnings.
Match on variants
Here is a function that transforms a colour variant type to an int.
The right-hand sides of each
when-clause is an expression. Sometimes
we might need statements to be processed before a value is given to
the clause. In that case, the
do expression comes handy. It enables
the opening of a block of statements like a function body, that is, a
block ended with a
return statement whose argument has the value of
the block, like so:
Matching records or tuples
Fields of records and components of tuples can be destructured. Record pattern variables can be renamed.
Pattern matching can also be used for nested patterns.