1# Freeform modules {#sec-freeform-modules} 2 3Freeform modules allow you to define values for option paths that have 4not been declared explicitly. This can be used to add attribute-specific 5types to what would otherwise have to be `attrsOf` options in order to 6accept all attribute names. 7 8This feature can be enabled by using the attribute `freeformType` to 9define a freeform type. By doing this, all assignments without an 10associated option will be merged using the freeform type and combined 11into the resulting `config` set. Since this feature nullifies name 12checking for entire option trees, it is only recommended for use in 13submodules. 14 15::: {#ex-freeform-module .example} 16::: {.title} 17**Example: Freeform submodule** 18::: 19The following shows a submodule assigning a freeform type that allows 20arbitrary attributes with `str` values below `settings`, but also 21declares an option for the `settings.port` attribute to have it 22type-checked and assign a default value. See 23[Example: Declaring a type-checked `settings` attribute](#ex-settings-typed-attrs) 24for a more complete example. 25 26```nix 27{ lib, config, ... }: { 28 29 options.settings = lib.mkOption { 30 type = lib.types.submodule { 31 32 freeformType = with lib.types; attrsOf str; 33 34 # We want this attribute to be checked for the correct type 35 options.port = lib.mkOption { 36 type = lib.types.port; 37 # Declaring the option also allows defining a default value 38 default = 8080; 39 }; 40 41 }; 42 }; 43} 44``` 45 46And the following shows what such a module then allows 47 48```nix 49{ 50 # Not a declared option, but the freeform type allows this 51 settings.logLevel = "debug"; 52 53 # Not allowed because the the freeform type only allows strings 54 # settings.enable = true; 55 56 # Allowed because there is a port option declared 57 settings.port = 80; 58 59 # Not allowed because the port option doesn't allow strings 60 # settings.port = "443"; 61} 62``` 63::: 64 65::: {.note} 66Freeform attributes cannot depend on other attributes of the same set 67without infinite recursion: 68 69```nix 70{ 71 # This throws infinite recursion encountered 72 settings.logLevel = lib.mkIf (config.settings.port == 80) "debug"; 73} 74``` 75 76To prevent this, declare options for all attributes that need to depend 77on others. For above example this means to declare `logLevel` to be an 78option. 79:::