summary refs log tree commit diff
path: root/nixos/doc/manual/from_md/development/option-types.section.xml
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/doc/manual/from_md/development/option-types.section.xml')
-rw-r--r--nixos/doc/manual/from_md/development/option-types.section.xml1038
1 files changed, 1038 insertions, 0 deletions
diff --git a/nixos/doc/manual/from_md/development/option-types.section.xml b/nixos/doc/manual/from_md/development/option-types.section.xml
new file mode 100644
index 00000000000..44472929270
--- /dev/null
+++ b/nixos/doc/manual/from_md/development/option-types.section.xml
@@ -0,0 +1,1038 @@
+<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xml:id="sec-option-types">
+  <title>Options Types</title>
+  <para>
+    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.
+  </para>
+  <section xml:id="sec-option-types-basic">
+    <title>Basic Types</title>
+    <para>
+      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.
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term>
+          <literal>types.bool</literal>
+        </term>
+        <listitem>
+          <para>
+            A boolean, its values can be <literal>true</literal> or
+            <literal>false</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.path</literal>
+        </term>
+        <listitem>
+          <para>
+            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 <literal>types.package</literal>
+            should be preferred.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.package</literal>
+        </term>
+        <listitem>
+          <para>
+            A top-level store path. This can be an attribute set
+            pointing to a store path, like a derivation or a flake
+            input.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.anything</literal>
+        </term>
+        <listitem>
+          <para>
+            A type that accepts any value and recursively merges
+            attribute sets together. This type is recommended when the
+            option type is unknown.
+          </para>
+          <anchor xml:id="ex-types-anything" />
+          <para>
+            <emphasis role="strong">Example:
+            <literal>types.anything</literal> Example</emphasis>
+          </para>
+          <para>
+            Two definitions of this type like
+          </para>
+          <programlisting language="bash">
+{
+  str = lib.mkDefault &quot;foo&quot;;
+  pkg.hello = pkgs.hello;
+  fun.fun = x: x + 1;
+}
+</programlisting>
+          <programlisting language="bash">
+{
+  str = lib.mkIf true &quot;bar&quot;;
+  pkg.gcc = pkgs.gcc;
+  fun.fun = lib.mkForce (x: x + 2);
+}
+</programlisting>
+          <para>
+            will get merged to
+          </para>
+          <programlisting language="bash">
+{
+  str = &quot;bar&quot;;
+  pkg.gcc = pkgs.gcc;
+  pkg.hello = pkgs.hello;
+  fun.fun = x: x + 2;
+}
+</programlisting>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.raw</literal>
+        </term>
+        <listitem>
+          <para>
+            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 <literal>mkForce</literal>,
+            <literal>mkIf</literal> 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.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.optionType</literal>
+        </term>
+        <listitem>
+          <para>
+            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 <literal>_module.freeformType</literal> option.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.attrs</literal>
+        </term>
+        <listitem>
+          <para>
+            A free-form attribute set.
+          </para>
+          <warning>
+            <para>
+              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
+              <literal>lib.mkDefault</literal>,
+              <literal>lib.mkIf</literal> and co. For allowing arbitrary
+              attribute sets, prefer
+              <literal>types.attrsOf types.anything</literal> instead
+              which doesn't have these problems.
+            </para>
+          </warning>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+    <para>
+      Integer-related types:
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term>
+          <literal>types.int</literal>
+        </term>
+        <listitem>
+          <para>
+            A signed integer.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.ints.{s8, s16, s32}</literal>
+        </term>
+        <listitem>
+          <para>
+            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.
+            <literal>−128</literal> to <literal>127</literal> for 8
+            bits).
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.ints.unsigned</literal>
+        </term>
+        <listitem>
+          <para>
+            An unsigned integer (that is &gt;= 0).
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.ints.{u8, u16, u32}</literal>
+        </term>
+        <listitem>
+          <para>
+            Unsigned integers with a fixed length (8, 16 or 32 bits).
+            They go from 0 to 2^n−1 respectively (e.g.
+            <literal>0</literal> to <literal>255</literal> for 8 bits).
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.ints.positive</literal>
+        </term>
+        <listitem>
+          <para>
+            A positive integer (that is &gt; 0).
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.port</literal>
+        </term>
+        <listitem>
+          <para>
+            A port number. This type is an alias to
+            <literal>types.ints.u16</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+    <para>
+      String-related types:
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term>
+          <literal>types.str</literal>
+        </term>
+        <listitem>
+          <para>
+            A string. Multiple definitions cannot be merged.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.lines</literal>
+        </term>
+        <listitem>
+          <para>
+            A string. Multiple definitions are concatenated with a new
+            line <literal>&quot;\n&quot;</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.commas</literal>
+        </term>
+        <listitem>
+          <para>
+            A string. Multiple definitions are concatenated with a comma
+            <literal>&quot;,&quot;</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.envVar</literal>
+        </term>
+        <listitem>
+          <para>
+            A string. Multiple definitions are concatenated with a
+            collon <literal>&quot;:&quot;</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.strMatching</literal>
+        </term>
+        <listitem>
+          <para>
+            A string matching a specific regular expression. Multiple
+            definitions cannot be merged. The regular expression is
+            processed using <literal>builtins.match</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </section>
+  <section xml:id="sec-option-types-value">
+    <title>Value Types</title>
+    <para>
+      Value types are types that take a value parameter.
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term>
+          <literal>types.enum</literal>
+          <emphasis><literal>l</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            One element of the list
+            <emphasis><literal>l</literal></emphasis>, e.g.
+            <literal>types.enum [ &quot;left&quot; &quot;right&quot; ]</literal>.
+            Multiple definitions cannot be merged.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.separatedString</literal>
+          <emphasis><literal>sep</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            A string with a custom separator
+            <emphasis><literal>sep</literal></emphasis>, e.g.
+            <literal>types.separatedString &quot;|&quot;</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.ints.between</literal>
+          <emphasis><literal>lowest highest</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            An integer between
+            <emphasis><literal>lowest</literal></emphasis> and
+            <emphasis><literal>highest</literal></emphasis> (both
+            inclusive). Useful for creating types like
+            <literal>types.port</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.submodule</literal>
+          <emphasis><literal>o</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            A set of sub options
+            <emphasis><literal>o</literal></emphasis>.
+            <emphasis><literal>o</literal></emphasis> 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
+            <literal>types.submoduleWith { modules = toList o; shorthandOnlyDefinesConfig = true; }</literal>.
+            Submodules are detailed in
+            <link linkend="section-option-types-submodule">Submodule</link>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.submoduleWith</literal> {
+          <emphasis><literal>modules</literal></emphasis>,
+          <emphasis><literal>specialArgs</literal></emphasis> ? {},
+          <emphasis><literal>shorthandOnlyDefinesConfig</literal></emphasis>
+          ? false }
+        </term>
+        <listitem>
+          <para>
+            Like <literal>types.submodule</literal>, but more flexible
+            and with better defaults. It has parameters
+          </para>
+          <itemizedlist>
+            <listitem>
+              <para>
+                <emphasis><literal>modules</literal></emphasis> 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.
+              </para>
+              <note>
+                <para>
+                  Only options defined with this argument are included
+                  in rendered documentation.
+                </para>
+              </note>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis><literal>specialArgs</literal></emphasis> An
+                attribute set of extra arguments to be passed to the
+                module functions. The option
+                <literal>_module.args</literal> should be used instead
+                for most arguments since it allows overriding.
+                <emphasis><literal>specialArgs</literal></emphasis>
+                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
+                <literal>lib</literal> argument, because
+                <literal>lib</literal> itself is used to define
+                <literal>_module.args</literal>, which makes using
+                <literal>_module.args</literal> to define it impossible.
+              </para>
+            </listitem>
+            <listitem>
+              <para>
+                <emphasis><literal>shorthandOnlyDefinesConfig</literal></emphasis>
+                Whether definitions of this type should default to the
+                <literal>config</literal> section of a module (see
+                <link linkend="ex-module-syntax">Example: Structure of
+                NixOS Modules</link>) if it is an attribute set.
+                Enabling this only has a benefit when the submodule
+                defines an option named <literal>config</literal> or
+                <literal>options</literal>. In such a case it would
+                allow the option to be set with
+                <literal>the-submodule.config = &quot;value&quot;</literal>
+                instead of requiring
+                <literal>the-submodule.config.config = &quot;value&quot;</literal>.
+                This is because only when modules
+                <emphasis>don't</emphasis> set the
+                <literal>config</literal> or <literal>options</literal>
+                keys, all keys are interpreted as option definitions in
+                the <literal>config</literal> section. Enabling this
+                option implicitly puts all attributes in the
+                <literal>config</literal> section.
+              </para>
+              <para>
+                With this option enabled, defining a
+                non-<literal>config</literal> section requires using a
+                function:
+                <literal>the-submodule = { ... }: { options = { ... }; }</literal>.
+              </para>
+            </listitem>
+          </itemizedlist>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </section>
+  <section xml:id="sec-option-types-composed">
+    <title>Composed Types</title>
+    <para>
+      Composed types are types that take a type as parameter.
+      <literal>listOf int</literal> and
+      <literal>either int str</literal> are examples of composed types.
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term>
+          <literal>types.listOf</literal>
+          <emphasis><literal>t</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            A list of <emphasis><literal>t</literal></emphasis> type,
+            e.g. <literal>types.listOf int</literal>. Multiple
+            definitions are merged with list concatenation.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.attrsOf</literal>
+          <emphasis><literal>t</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            An attribute set of where all the values are of
+            <emphasis><literal>t</literal></emphasis> type. Multiple
+            definitions result in the joined attribute set.
+          </para>
+          <note>
+            <para>
+              This type is <emphasis>strict</emphasis> in its values,
+              which in turn means attributes cannot depend on other
+              attributes. See <literal> types.lazyAttrsOf</literal> for
+              a lazy version.
+            </para>
+          </note>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.lazyAttrsOf</literal>
+          <emphasis><literal>t</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            An attribute set of where all the values are of
+            <emphasis><literal>t</literal></emphasis> type. Multiple
+            definitions result in the joined attribute set. This is the
+            lazy version of <literal>types.attrsOf </literal>, allowing
+            attributes to depend on each other.
+          </para>
+          <warning>
+            <para>
+              This version does not fully support conditional
+              definitions! With an option <literal>foo</literal> of this
+              type and a definition
+              <literal>foo.attr = lib.mkIf false 10</literal>,
+              evaluating <literal>foo ? attr</literal> will return
+              <literal>true</literal> even though it should be false.
+              Accessing the value will then throw an error. For types
+              <emphasis><literal>t</literal></emphasis> that have an
+              <literal>emptyValue</literal> defined, that value will be
+              returned instead of throwing an error. So if the type of
+              <literal>foo.attr</literal> was
+              <literal>lazyAttrsOf (nullOr int)</literal>,
+              <literal>null</literal> would be returned instead for the
+              same <literal>mkIf false</literal> definition.
+            </para>
+          </warning>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.nullOr</literal>
+          <emphasis><literal>t</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            <literal>null</literal> or type
+            <emphasis><literal>t</literal></emphasis>. Multiple
+            definitions are merged according to type
+            <emphasis><literal>t</literal></emphasis>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.uniq</literal>
+          <emphasis><literal>t</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            Ensures that type <emphasis><literal>t</literal></emphasis>
+            cannot be merged. It is used to ensure option definitions
+            are declared only once.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.unique</literal>
+          <literal>{ message = m }</literal>
+          <emphasis><literal>t</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            Ensures that type <emphasis><literal>t</literal></emphasis>
+            cannot be merged. Prints the message
+            <emphasis><literal>m</literal></emphasis>, after the line
+            <literal>The option &lt;option path&gt; is defined multiple times.</literal>
+            and before a list of definition locations.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.either</literal>
+          <emphasis><literal>t1 t2</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            Type <emphasis><literal>t1</literal></emphasis> or type
+            <emphasis><literal>t2</literal></emphasis>, e.g.
+            <literal>with types; either int str</literal>. Multiple
+            definitions cannot be merged.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.oneOf</literal> [
+          <emphasis><literal>t1 t2</literal></emphasis> ... ]
+        </term>
+        <listitem>
+          <para>
+            Type <emphasis><literal>t1</literal></emphasis> or type
+            <emphasis><literal>t2</literal></emphasis> and so forth,
+            e.g. <literal>with types; oneOf [ int str bool ]</literal>.
+            Multiple definitions cannot be merged.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>types.coercedTo</literal>
+          <emphasis><literal>from f to</literal></emphasis>
+        </term>
+        <listitem>
+          <para>
+            Type <emphasis><literal>to</literal></emphasis> or type
+            <emphasis><literal>from</literal></emphasis> which will be
+            coerced to type <emphasis><literal>to</literal></emphasis>
+            using function <emphasis><literal>f</literal></emphasis>
+            which takes an argument of type
+            <emphasis><literal>from</literal></emphasis> and return a
+            value of type <emphasis><literal>to</literal></emphasis>.
+            Can be used to preserve backwards compatibility of an option
+            if its type was changed.
+          </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </section>
+  <section xml:id="section-option-types-submodule">
+    <title>Submodule</title>
+    <para>
+      <literal>submodule</literal> is a very powerful type that defines
+      a set of sub-options that are handled like a separate module.
+    </para>
+    <para>
+      It takes a parameter <emphasis><literal>o</literal></emphasis>,
+      that should be a set, or a function returning a set with an
+      <literal>options</literal> key defining the sub-options. Submodule
+      option definitions are type-checked accordingly to the
+      <literal>options</literal> declarations. Of course, you can nest
+      submodule option definitons for even higher modularity.
+    </para>
+    <para>
+      The option set can be defined directly
+      (<link linkend="ex-submodule-direct">Example: Directly defined
+      submodule</link>) or as reference
+      (<link linkend="ex-submodule-reference">Example: Submodule defined
+      as a reference</link>).
+    </para>
+    <anchor xml:id="ex-submodule-direct" />
+    <para>
+      <emphasis role="strong">Example: Directly defined
+      submodule</emphasis>
+    </para>
+    <programlisting language="bash">
+options.mod = mkOption {
+  description = &quot;submodule example&quot;;
+  type = with types; submodule {
+    options = {
+      foo = mkOption {
+        type = int;
+      };
+      bar = mkOption {
+        type = str;
+      };
+    };
+  };
+};
+</programlisting>
+    <anchor xml:id="ex-submodule-reference" />
+    <para>
+      <emphasis role="strong">Example: Submodule defined as a
+      reference</emphasis>
+    </para>
+    <programlisting language="bash">
+let
+  modOptions = {
+    options = {
+      foo = mkOption {
+        type = int;
+      };
+      bar = mkOption {
+        type = int;
+      };
+    };
+  };
+in
+options.mod = mkOption {
+  description = &quot;submodule example&quot;;
+  type = with types; submodule modOptions;
+};
+</programlisting>
+    <para>
+      The <literal>submodule</literal> type is especially interesting
+      when used with composed types like <literal>attrsOf</literal> or
+      <literal>listOf</literal>. When composed with
+      <literal>listOf</literal>
+      (<link linkend="ex-submodule-listof-declaration">Example:
+      Declaration of a list of submodules</link>),
+      <literal>submodule</literal> allows multiple definitions of the
+      submodule option set
+      (<link linkend="ex-submodule-listof-definition">Example:
+      Definition of a list of submodules</link>).
+    </para>
+    <anchor xml:id="ex-submodule-listof-declaration" />
+    <para>
+      <emphasis role="strong">Example: Declaration of a list of
+      submodules</emphasis>
+    </para>
+    <programlisting language="bash">
+options.mod = mkOption {
+  description = &quot;submodule example&quot;;
+  type = with types; listOf (submodule {
+    options = {
+      foo = mkOption {
+        type = int;
+      };
+      bar = mkOption {
+        type = str;
+      };
+    };
+  });
+};
+</programlisting>
+    <anchor xml:id="ex-submodule-listof-definition" />
+    <para>
+      <emphasis role="strong">Example: Definition of a list of
+      submodules</emphasis>
+    </para>
+    <programlisting language="bash">
+config.mod = [
+  { foo = 1; bar = &quot;one&quot;; }
+  { foo = 2; bar = &quot;two&quot;; }
+];
+</programlisting>
+    <para>
+      When composed with <literal>attrsOf</literal>
+      (<link linkend="ex-submodule-attrsof-declaration">Example:
+      Declaration of attribute sets of submodules</link>),
+      <literal>submodule</literal> allows multiple named definitions of
+      the submodule option set
+      (<link linkend="ex-submodule-attrsof-definition">Example:
+      Definition of attribute sets of submodules</link>).
+    </para>
+    <anchor xml:id="ex-submodule-attrsof-declaration" />
+    <para>
+      <emphasis role="strong">Example: Declaration of attribute sets of
+      submodules</emphasis>
+    </para>
+    <programlisting language="bash">
+options.mod = mkOption {
+  description = &quot;submodule example&quot;;
+  type = with types; attrsOf (submodule {
+    options = {
+      foo = mkOption {
+        type = int;
+      };
+      bar = mkOption {
+        type = str;
+      };
+    };
+  });
+};
+</programlisting>
+    <anchor xml:id="ex-submodule-attrsof-definition" />
+    <para>
+      <emphasis role="strong">Example: Definition of attribute sets of
+      submodules</emphasis>
+    </para>
+    <programlisting language="bash">
+config.mod.one = { foo = 1; bar = &quot;one&quot;; };
+config.mod.two = { foo = 2; bar = &quot;two&quot;; };
+</programlisting>
+  </section>
+  <section xml:id="sec-option-types-extending">
+    <title>Extending types</title>
+    <para>
+      Types are mainly characterized by their <literal>check</literal>
+      and <literal>merge</literal> functions.
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term>
+          <literal>check</literal>
+        </term>
+        <listitem>
+          <para>
+            The function to type check the value. Takes a value as
+            parameter and return a boolean. It is possible to extend a
+            type check with the <literal>addCheck</literal> function
+            (<link linkend="ex-extending-type-check-1">Example: Adding a
+            type check</link>), or to fully override the check function
+            (<link linkend="ex-extending-type-check-2">Example:
+            Overriding a type check</link>).
+          </para>
+          <anchor xml:id="ex-extending-type-check-1" />
+          <para>
+            <emphasis role="strong">Example: Adding a type
+            check</emphasis>
+          </para>
+          <programlisting language="bash">
+byte = mkOption {
+  description = &quot;An integer between 0 and 255.&quot;;
+  type = types.addCheck types.int (x: x &gt;= 0 &amp;&amp; x &lt;= 255);
+};
+</programlisting>
+          <anchor xml:id="ex-extending-type-check-2" />
+          <para>
+            <emphasis role="strong">Example: Overriding a type
+            check</emphasis>
+          </para>
+          <programlisting language="bash">
+nixThings = mkOption {
+  description = &quot;words that start with 'nix'&quot;;
+  type = types.str // {
+    check = (x: lib.hasPrefix &quot;nix&quot; x)
+  };
+};
+</programlisting>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>merge</literal>
+        </term>
+        <listitem>
+          <para>
+            Function to merge the options values when multiple values
+            are set. The function takes two parameters,
+            <literal>loc</literal> the option path as a list of strings,
+            and <literal>defs</literal> the list of defined values as a
+            list. It is possible to override a type merge function for
+            custom needs.
+          </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </section>
+  <section xml:id="sec-option-types-custom">
+    <title>Custom Types</title>
+    <para>
+      Custom types can be created with the
+      <literal>mkOptionType</literal> function. As type creation
+      includes some more complex topics such as submodule handling, it
+      is recommended to get familiar with <literal>types.nix</literal>
+      code before creating a new type.
+    </para>
+    <para>
+      The only required parameter is <literal>name</literal>.
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term>
+          <literal>name</literal>
+        </term>
+        <listitem>
+          <para>
+            A string representation of the type function name.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>definition</literal>
+        </term>
+        <listitem>
+          <para>
+            Description of the type used in documentation. Give
+            information of the type and any of its arguments.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>check</literal>
+        </term>
+        <listitem>
+          <para>
+            A function to type check the definition value. Takes the
+            definition value as a parameter and returns a boolean
+            indicating the type check result, <literal>true</literal>
+            for success and <literal>false</literal> for failure.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>merge</literal>
+        </term>
+        <listitem>
+          <para>
+            A function to merge multiple definitions values. Takes two
+            parameters:
+          </para>
+          <variablelist>
+            <varlistentry>
+              <term>
+                <emphasis><literal>loc</literal></emphasis>
+              </term>
+              <listitem>
+                <para>
+                  The option path as a list of strings, e.g.
+                  <literal>[&quot;boot&quot; &quot;loader &quot;grub&quot; &quot;enable&quot;]</literal>.
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>
+                <emphasis><literal>defs</literal></emphasis>
+              </term>
+              <listitem>
+                <para>
+                  The list of sets of defined <literal>value</literal>
+                  and <literal>file</literal> where the value was
+                  defined, e.g.
+                  <literal>[ { file = &quot;/foo.nix&quot;; value = 1; } { file = &quot;/bar.nix&quot;; value = 2 } ]</literal>.
+                  The <literal>merge</literal> function should return
+                  the merged value or throw an error in case the values
+                  are impossible or not meant to be merged.
+                </para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>getSubOptions</literal>
+        </term>
+        <listitem>
+          <para>
+            For composed types that can take a submodule as type
+            parameter, this function generate sub-options documentation.
+            It takes the current option prefix as a list and return the
+            set of sub-options. Usually defined in a recursive manner by
+            adding a term to the prefix, e.g.
+            <literal>prefix: elemType.getSubOptions (prefix ++ [&quot;prefix&quot;])</literal>
+            where
+            <emphasis><literal>&quot;prefix&quot;</literal></emphasis>
+            is the newly added prefix.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>getSubModules</literal>
+        </term>
+        <listitem>
+          <para>
+            For composed types that can take a submodule as type
+            parameter, this function should return the type parameters
+            submodules. If the type parameter is called
+            <literal>elemType</literal>, the function should just
+            recursively look into submodules by returning
+            <literal>elemType.getSubModules;</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>substSubModules</literal>
+        </term>
+        <listitem>
+          <para>
+            For composed types that can take a submodule as type
+            parameter, this function can be used to substitute the
+            parameter of a submodule type. It takes a module as
+            parameter and return the type with the submodule options
+            substituted. It is usually defined as a type function call
+            with a recursive call to <literal>substSubModules</literal>,
+            e.g for a type <literal>composedType</literal> that take an
+            <literal>elemtype</literal> type parameter, this function
+            should be defined as
+            <literal>m: composedType (elemType.substSubModules m)</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>typeMerge</literal>
+        </term>
+        <listitem>
+          <para>
+            A function to merge multiple type declarations. Takes the
+            type to merge <literal>functor</literal> as parameter. A
+            <literal>null</literal> return value means that type cannot
+            be merged.
+          </para>
+          <variablelist>
+            <varlistentry>
+              <term>
+                <emphasis><literal>f</literal></emphasis>
+              </term>
+              <listitem>
+                <para>
+                  The type to merge <literal>functor</literal>.
+                </para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+          <para>
+            Note: There is a generic <literal>defaultTypeMerge</literal>
+            that work with most of value and composed types.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <literal>functor</literal>
+        </term>
+        <listitem>
+          <para>
+            An attribute set representing the type. It is used for type
+            operations and has the following keys:
+          </para>
+          <variablelist>
+            <varlistentry>
+              <term>
+                <literal>type</literal>
+              </term>
+              <listitem>
+                <para>
+                  The type function.
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>
+                <literal>wrapped</literal>
+              </term>
+              <listitem>
+                <para>
+                  Holds the type parameter for composed types.
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>
+                <literal>payload</literal>
+              </term>
+              <listitem>
+                <para>
+                  Holds the value parameter for value types. The types
+                  that have a <literal>payload</literal> are the
+                  <literal>enum</literal>,
+                  <literal>separatedString</literal> and
+                  <literal>submodule</literal> types.
+                </para>
+              </listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>
+                <literal>binOp</literal>
+              </term>
+              <listitem>
+                <para>
+                  A binary operation that can merge the payloads of two
+                  same types. Defined as a function that take two
+                  payloads as parameters and return the payloads merged.
+                </para>
+              </listitem>
+            </varlistentry>
+          </variablelist>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </section>
+</section>