lib.types: add types.option

Signed-off-by: cinereal <cinereal@riseup.net>
This commit is contained in:
cinereal
2026-04-02 12:10:29 +02:00
parent 4a9a590d26
commit 7334dd9096
4 changed files with 41 additions and 0 deletions
+3
View File
@@ -704,6 +704,9 @@ 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
# Test that types.optionType merges types correctly
checkConfigOutput '^10$' config.theOption.int ./optionTypeMerging.nix
checkConfigOutput '^"hello"$' config.theOption.str ./optionTypeMerging.nix
+15
View File
@@ -0,0 +1,15 @@
{ config, lib, ... }:
{
options = {
theOption = lib.mkOption {
type = lib.types.optionDeclaration;
};
anOption = config.theOption;
};
config = {
theOption = lib.mkOption {
type = lib.types.int;
};
anOption = 10;
};
}
+7
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";
@@ -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.