# Options Types {#sec-option-types} Option types are a way to put constraints on the values a module option can take. Types are also responsible of how values are merged in case of multiple value definitions. ## Basic types {#sec-option-types-basic} Basic types are the simplest available types in the module system. Basic types include multiple string types that mainly differ in how definition merging is handled. `types.bool` : A boolean, its values can be `true` or `false`. All definitions must have the same value, after priorities. An error is thrown in case of a conflict. `types.boolByOr` : A boolean, its values can be `true` or `false`. The result is `true` if _any_ of multiple definitions is `true`. In other words, definitions are merged with the logical _OR_ operator. `types.path` : A filesystem path is anything that starts with a slash when coerced to a string. Even if derivations can be considered as paths, the more specific `types.package` should be preferred. `types.pathInStore` : A path that is contained in the Nix store. This can be a top-level store path like `pkgs.hello` or a descendant like `"${pkgs.hello}/bin/hello"`. `types.package` : A top-level store path. This can be an attribute set pointing to a store path, like a derivation or a flake input. `types.enum` *`l`* : One element of the list *`l`*, e.g. `types.enum [ "left" "right" ]`. Multiple definitions cannot be merged. If you want to pair these values with more information, possibly of distinct types, consider using a [sum type](#sec-option-types-sums). `types.anything` : A type that accepts any value and recursively merges attribute sets together. This type is recommended when the option type is unknown. ::: {#ex-types-anything .example} ### `types.anything` Two definitions of this type like ```nix { str = lib.mkDefault "foo"; pkg.hello = pkgs.hello; fun.fun = x: x + 1; } ``` ```nix { str = lib.mkIf true "bar"; pkg.gcc = pkgs.gcc; fun.fun = lib.mkForce (x: x + 2); } ``` will get merged to ```nix { str = "bar"; pkg.gcc = pkgs.gcc; pkg.hello = pkgs.hello; fun.fun = x: x + 2; } ``` ::: `types.raw` : A type which doesn't do any checking, merging or nested evaluation. It accepts a single arbitrary value that is not recursed into, making it useful for values coming from outside the module system, such as package sets or arbitrary data. Options of this type are still evaluated according to priorities and conditionals, so `mkForce`, `mkIf` and co. still work on the option value itself, but not for any value nested within it. This type should only be used when checking, merging and nested evaluation are not desirable. `types.optionType` : The type of an option's type. Its merging operation ensures that nested options have the correct file location annotated, and that if possible, multiple option definitions are correctly merged together. The main use case is as the type of the `_module.freeformType` option. `types.attrs` : A free-form attribute set. ::: {.warning} This type will be deprecated in the future because it doesn't recurse into attribute sets, silently drops earlier attribute definitions, and doesn't discharge `lib.mkDefault`, `lib.mkIf` and co. For allowing arbitrary attribute sets, prefer `types.attrsOf types.anything` instead which doesn't have these problems. ::: `types.pkgs` : A type for the top level Nixpkgs package set. ### Numeric types {#sec-option-types-numeric} `types.int` : A signed integer. `types.ints.{s8, s16, s32}` : Signed integers with a fixed length (8, 16 or 32 bits). They go from −2^n/2 to 2^n/2−1 respectively (e.g. `−128` to `127` for 8 bits). `types.ints.unsigned` : An unsigned integer (that is >= 0). `types.ints.{u8, u16, u32}` : Unsigned integers with a fixed length (8, 16 or 32 bits). They go from 0 to 2^n−1 respectively (e.g. `0` to `255` for 8 bits). `types.ints.between` *`lowest highest`* : An integer between *`lowest`* and *`highest`* (both inclusive). `types.ints.positive` : A positive integer (that is > 0). `types.port` : A port number. This type is an alias to `types.ints.u16`. `types.float` : A floating point number. ::: {.warning} Converting a floating point number to a string with `toString` or `toJSON` may result in [precision loss](https://github.com/NixOS/nix/issues/5733). ::: `types.number` : Either a signed integer or a floating point number. No implicit conversion is done between the two types, and multiple equal definitions will only be merged if they have the same type. `types.numbers.between` *`lowest highest`* : An integer or floating point number between *`lowest`* and *`highest`* (both inclusive). `types.numbers.nonnegative` : A nonnegative integer or floating point number (that is >= 0). `types.numbers.positive` : A positive integer or floating point number (that is > 0). ### String types {#sec-option-types-string} `types.str` : A string. Multiple definitions cannot be merged. `types.separatedString` *`sep`* : A string. Multiple definitions are concatenated with *`sep`*, e.g. `types.separatedString "|"`. `types.lines` : A string. Multiple definitions are concatenated with a new line `"\n"`. `types.commas` : A string. Multiple definitions are concatenated with a comma `","`. `types.envVar` : A string. Multiple definitions are concatenated with a colon `":"`. `types.strMatching` : A string matching a specific regular expression. Multiple definitions cannot be merged. The regular expression is processed using `builtins.match`. ## Submodule types {#sec-option-types-submodule} Submodules are detailed in [Submodule](#section-option-types-submodule). `types.submodule` *`o`* : A set of sub options *`o`*. *`o`* can be an attribute set, a function returning an attribute set, or a path to a file containing such a value. Submodules are used in composed types to create modular options. This is equivalent to `types.submoduleWith { modules = toList o; shorthandOnlyDefinesConfig = true; }`. `types.submoduleWith` { *`modules`*, *`specialArgs`* ? {}, *`shorthandOnlyDefinesConfig`* ? false } : Like `types.submodule`, but more flexible and with better defaults. It has parameters - *`modules`* A list of modules to use by default for this submodule type. This gets combined with all option definitions to build the final list of modules that will be included. ::: {.note} Only options defined with this argument are included in rendered documentation. ::: - *`specialArgs`* An attribute set of extra arguments to be passed to the module functions. The option `_module.args` should be used instead for most arguments since it allows overriding. *`specialArgs`* should only be used for arguments that can't go through the module fixed-point, because of infinite recursion or other problems. An example is overriding the `lib` argument, because `lib` itself is used to define `_module.args`, which makes using `_module.args` to define it impossible. - *`shorthandOnlyDefinesConfig`* Whether definitions of this type should default to the `config` section of a module (see [Example: Structure of NixOS Modules](#ex-module-syntax)) if it is an attribute set. Enabling this only has a benefit when the submodule defines an option named `config` or `options`. In such a case it would allow the option to be set with `the-submodule.config = "value"` instead of requiring `the-submodule.config.config = "value"`. This is because only when modules *don't* set the `config` or `options` keys, all keys are interpreted as option definitions in the `config` section. Enabling this option implicitly puts all attributes in the `config` section. With this option enabled, defining a non-`config` section requires using a function: `the-submodule = { ... }: { options = { ... }; }`. `types.deferredModule` : Whereas `submodule` represents an option tree, `deferredModule` represents a module value, such as a module file or a configuration. It can be set multiple times. Module authors can use its value in `imports`, in `submoduleWith`'s `modules` or in `evalModules`' `modules` parameter, among other places. Note that `imports` must be evaluated before the module fixpoint. Because of this, deferred modules can only be imported into "other" fixpoints, such as submodules. One use case for this type is the type of a "default" module that allow the user to affect all submodules in an `attrsOf submodule` at once. This is more convenient and discoverable than expecting the module user to type-merge with the `attrsOf submodule` option. ## Union types {#sec-option-types-unions} A union of types is a type such that a value is valid when it is valid for at least one of those types. If some values are instances of more than one of the types, it is not possible to distinguish which type they are meant to be instances of. If that's needed, consider using a [sum type](#sec-option-types-sums). `types.either` *`t1 t2`* : Type *`t1`* or type *`t2`*, e.g. `with types; either int str`. Multiple definitions cannot be merged. `types.oneOf` \[ *`t1 t2`* ... \] : Type *`t1`* or type *`t2`* and so forth, e.g. `with types; oneOf [ int str bool ]`. Multiple definitions cannot be merged. `types.nullOr` *`t`* : `null` or type *`t`*. Multiple definitions are merged according to type *`t`*. ## Sum types {#sec-option-types-sums} A sum type can be thought of, conceptually, as a *`types.enum`* where each valid item is paired with at least a type, through some value syntax. Nix does not have a built-in syntax for this pairing of a label and a type or value, so sum types may be represented in multiple ways. If the you're interested in can be distinguished without a label, you may simplify your value syntax with a [union type](#sec-option-types-unions) instead. `types.attrTag` *`{ attr1 = option1; attr2 = option2; ... }`* : An attribute set containing one attribute, whose name must be picked from the attribute set (`attr1`, etc) and whose value consists of definitions that are valid for the corresponding option (`option1`, etc). This type appears in the documentation as _attribute-tagged union_. Example: ```nix { lib, ... }: let inherit (lib) type mkOption; in { options.toyRouter.rules = mkOption { description = '' Rules for a fictional packet routing service. ''; type = types.attrsOf ( types.attrTag { bounce = mkOption { description = "Send back a packet explaining why it wasn't forwarded."; type = types.submodule { options.errorMessage = mkOption { … }; }; }; forward = mkOption { description = "Forward the packet."; type = types.submodule { options.destination = mkOption { … }; }; }; ignore = types.mkOption { description = "Drop the packet without sending anything back."; type = types.submodule {}; }; }); }; config.toyRouter.rules = { http = { bounce = { errorMessage = "Unencrypted HTTP is banned. You must always use https://."; }; }; ssh = { drop = {}; }; }; } ``` ## Composed types {#sec-option-types-composed} Composed types are types that take a type as parameter. `listOf int` and `either int str` are examples of composed types. `types.listOf` *`t`* : A list of *`t`* type, e.g. `types.listOf int`. Multiple definitions are merged with list concatenation. `types.attrsOf` *`t`* : An attribute set of where all the values are of *`t`* type. Multiple definitions result in the joined attribute set. ::: {.note} This type is *strict* in its values, which in turn means attributes cannot depend on other attributes. See ` types.lazyAttrsOf` for a lazy version. ::: `types.lazyAttrsOf` *`t`* : An attribute set of where all the values are of *`t`* type. Multiple definitions result in the joined attribute set. This is the lazy version of `types.attrsOf `, allowing attributes to depend on each other. ::: {.warning} This version does not fully support conditional definitions! With an option `foo` of this type and a definition `foo.attr = lib.mkIf false 10`, evaluating `foo ? attr` will return `true` even though it should be false. Accessing the value will then throw an error. For types *`t`* that have an `emptyValue` defined, that value will be returned instead of throwing an error. So if the type of `foo.attr` was `lazyAttrsOf (nullOr int)`, `null` would be returned instead for the same `mkIf false` definition. ::: `types.uniq` *`t`* : Ensures that type *`t`* cannot be merged. It is used to ensure option definitions are provided only once. `types.unique` `{ message = m }` *`t`* : Ensures that type *`t`* cannot be merged. Prints the message *`m`*, after the line `The option