Type combinators
Here's some information about some special types combining other types.
types.union
: Either of multiple types
You can use types.union(int, str)
to indicate that a field depends on either an integer or a string.
Unions are ordered. This means that types.union(int, float) != types.union(float, int)
.
This is relevant when two or more types in the union can accept the same native type, with differing checks or casts. In the case of int
and float
, the integer 5
will remain the integer 5
when casting to types.union(int, float)
, but will be casted to the float 5.0
when casted to types.union(float, int)
. (Of course, a float such as 4.0
will remain a float in both cases, since it isn't accepted by int
).
Optional and smart types
For fields that can be set to none
to indicate absence, use types.option(typ)
. This is the same as types.union(none, typ)
.
For fields with a smart default indicated by auto
, use types.smart(typ)
. This is the same as types.union(auto, typ)
.
You can also combine both: types.option(e.types.smart(typ))
is the same as types.union(none, auto, typ)
.
Folding in unions
Folding is preserved in unions unless it's ambiguous. For example, it is preserved for types.union(int, stroke, array)
: two arrays of this type are joined, a length and a color are cast to stroke
and combined into a single length + color
stroke, and integers have no folding and stay that way (the latest integer has priority).
However, if you have types.union(types.array(int), types.array(float))
, folding is disabled (the latest array overrides the previous) as it is not straightforward to tell to which type an array could belong, so we avoid creating an invalid instance of this type (which could happen if we joined an int array with a float array).
types.exact
: Disable casting for a type
You can use types.exact(typ)
to ensure there is no casting involved for this type. For example, types.exact(float)
ensures integers won't cast to floats (they are normally accepted). Also, types.exact(stroke)
ensures only stroke(5pt)
can be passed to a field with that type, not 5pt
itself. Finally, types.exact(my-custom-type)
, where my-custom-type
has custom casts from existing types, disables those casts, allowing only an instance of my-custom-type
itself to be used for a field with that type.
types.array
: Array of a type
You can use types.array(typ)
to accept arrays of elements of the same type.
types.dict
: Dictionary with values of a type
You can use types.dict(typ)
to accept dictionaries with values of the same type. (Note that dictionary keys are all strings.)
For example, (a: 5, b: 6)
is a valid dict(int)
, but not a valid dict(str)
.