lib.types: add types.option (#499945)

This commit is contained in:
Robert Hensing 2026-04-08 13:41:10 +00:00 committed by GitHub
commit 8d4e372952
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 54 additions and 0 deletions

View file

@ -717,6 +717,10 @@ checkConfigError 'In module .*/options-type-error-configuration.nix: expected an
# Check that that merging of option collisions doesn't depend on type being set
checkConfigError 'The option .group..*would be a parent of the following options, but its type .<no description>. does not support nested options.\n\s*- option.s. with prefix .group.enable..*' config.group.enable ./merge-typeless-option.nix
# types.optionDeclaration
checkConfigOutput '^10$' config.anOption ./option.nix
checkConfigError 'A definition for option .aBadOptionDef. is not of type .option declaration.' config.aBadOptionDef ./option.nix
# Test that types.optionType merges types correctly
checkConfigOutput '^10$' config.theOption.int ./optionTypeMerging.nix
checkConfigOutput '^"hello"$' config.theOption.str ./optionTypeMerging.nix

View file

@ -0,0 +1,27 @@
{
config,
lib,
options,
...
}:
{
options = {
theOption = lib.mkOption {
type = lib.types.optionDeclaration;
};
anOption = config.theOption;
aBadOptionDef = lib.mkOption {
type = lib.types.optionDeclaration;
description = ''
This option is perfectly fine, but will have a bad definition.
'';
};
};
config = {
theOption = lib.mkOption {
type = lib.types.int;
};
anOption = 10;
aBadOptionDef = options.theOption; # Not a declaration
};
}

View file

@ -1180,6 +1180,13 @@ rec {
};
};
optionDeclaration = mkOptionType {
name = "optionDeclaration";
description = "option declaration";
descriptionClass = "noun";
check = opt: isType "option" opt && !(opt ? value);
};
# The type of a type!
optionType = mkOptionType {
name = "optionType";

View file

@ -137,6 +137,22 @@ Users must still be careful about how they reference these paths.
multiple option definitions are correctly merged together. The main use
case is as the type of the `_module.freeformType` option.
`types.optionDeclaration`
: The type of a module system option declaration, as created by `lib.mkOption`.
This allows an option to hold another option declaration as its value, which
can then be spliced into a module's `options` attrset. Note that this only
accepts option declarations, not evaluated options (i.e. options that have
been processed by `evalModules` and have a `value` field).
::: {.warning}
Use of this type is a form of metaprogramming that makes modules harder
to reason about, since options and their types become dynamic values
rather than statically declared structure. Prefer conventional module
patterns where possible, and only reach for `types.optionDeclaration` when the
added complexity is justified.
:::
`types.attrs`
: A free-form attribute set.