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### Freeform submodule 17 18The following shows a submodule assigning a freeform type that allows 19arbitrary attributes with `str` values below `settings`, but also 20declares an option for the `settings.port` attribute to have it 21type-checked and assign a default value. See 22[Example: Declaring a type-checked `settings` attribute](#ex-settings-typed-attrs) 23for a more complete example. 24 25```nix 26{ lib, config, ... }: { 27 28 options.settings = lib.mkOption { 29 type = lib.types.submodule { 30 31 freeformType = with lib.types; attrsOf str; 32 33 # We want this attribute to be checked for the correct type 34 options.port = lib.mkOption { 35 type = lib.types.port; 36 # Declaring the option also allows defining a default value 37 default = 8080; 38 }; 39 40 }; 41 }; 42} 43``` 44 45And the following shows what such a module then allows 46 47```nix 48{ 49 # Not a declared option, but the freeform type allows this 50 settings.logLevel = "debug"; 51 52 # Not allowed because the the freeform type only allows strings 53 # settings.enable = true; 54 55 # Allowed because there is a port option declared 56 settings.port = 80; 57 58 # Not allowed because the port option doesn't allow strings 59 # settings.port = "443"; 60} 61``` 62::: 63 64::: {.note} 65Freeform attributes cannot depend on other attributes of the same set 66without infinite recursion: 67 68```nix 69{ 70 # This throws infinite recursion encountered 71 settings.logLevel = lib.mkIf (config.settings.port == 80) "debug"; 72} 73``` 74 75To prevent this, declare options for all attributes that need to depend 76on others. For above example this means to declare `logLevel` to be an 77option. 78:::