Skip to content

Types and defaults

yen has no type system of its own. A type is any value with check = value: bool. lib.types from nixpkgs works, a kind works (see Instances and refs), and yen.lib.is makes a type from any function.

ConstructorDefault
lib.types.str, any typenone: the field is required
yen.lib.opt type valuevalue
yen.lib.maybe typenull
yen.lib.derive type (self: …)computed from the instance itself
yen.lib.is (v: …)none: a type from a check function
modules/host.nix
# A type is anything with `check = value: bool`. yen adds defaults on top of it.
{ yen, lib, ... }:
let
inherit (yen.lib)
opt
maybe
derive
is
;
in
{
yen.kinds.host.fields = {
addr = lib.types.str; # required
port = opt lib.types.port 22; # a default
jump = maybe lib.types.str; # null by default
vpn = derive lib.types.str (self: "vpn-${self.name}"); # a default computed from the instance
tags = opt (is (v: lib.isList v && lib.all lib.isString v)) [ ]; # your own check
settings.kernel.channel = opt (lib.types.enum [
"lts"
"latest"
]) "lts"; # nested fields
};
}

Fields can nest. settings.kernel.channel is one field at a path, with its own type and default. An instance gives only what it needs:

modules/hosts.nix
{ yen, ... }:
{
yen.host.web.addr = "10.0.0.1";
yen.host.db = {
addr = "10.0.0.2";
port = 2222;
vpn = "vpn-database"; # an explicit value wins over `derive`
settings.kernel.channel = "latest";
};
}

The read of a field looks at the instance first, then at the default, then checks the value:

result
{
db = {
channel = "latest";
jump = null;
port = 2222;
tags = [ ];
vpn = "vpn-database";
};
web = {
channel = "lts";
jump = null;
port = 22;
tags = [ ];
vpn = "vpn-web";
};
}
Contribute Community Sponsor