github.com/iaas-resource-provision/iaas-rpc@v1.0.7-0.20211021023331-ed21f798c408/website/docs/language/expressions/type-constraints.html.md (about) 1 --- 2 layout: "language" 3 page_title: "Type Constraints - Configuration Language" 4 sidebar_current: "docs-config-types" 5 description: |- 6 Terraform module authors and provider developers can use detailed type 7 constraints to validate the inputs of their modules and resources. 8 --- 9 10 # Type Constraints 11 12 Terraform module authors and provider developers can use detailed type 13 constraints to validate user-provided values for their input variables and 14 resource arguments. This requires some additional knowledge about Terraform's 15 type system, but allows you to build a more resilient user interface for your 16 modules and resources. 17 18 ## Type Keywords and Constructors 19 20 Type constraints are expressed using a mixture of _type keywords_ and 21 function-like constructs called _type constructors._ 22 23 * Type keywords are unquoted symbols that represent a static type. 24 * Type constructors are unquoted symbols followed by a pair of 25 parentheses, which contain an argument that specifies more information about 26 the type. Without its argument, a type constructor does not fully 27 represent a type; instead, it represents a _kind_ of similar types. 28 29 Type constraints look like other kinds of Terraform 30 [expressions](/docs/language/expressions/index.html), but are a special syntax. Within the 31 Terraform language, they are only valid in the `type` argument of an 32 [input variable](/docs/language/values/variables.html). 33 34 ## Primitive Types 35 36 A _primitive_ type is a simple type that isn't made from any other types. All 37 primitive types in Terraform are represented by a type keyword. The available 38 primitive types are: 39 40 * `string`: a sequence of Unicode characters representing some text, such 41 as `"hello"`. 42 * `number`: a numeric value. The `number` type can represent both whole 43 numbers like `15` and fractional values such as `6.283185`. 44 * `bool`: either `true` or `false`. `bool` values can be used in conditional 45 logic. 46 47 ### Conversion of Primitive Types 48 49 The Terraform language will automatically convert `number` and `bool` values 50 to `string` values when needed, and vice-versa as long as the string contains 51 a valid representation of a number or boolean value. 52 53 * `true` converts to `"true"`, and vice-versa 54 * `false` converts to `"false"`, and vice-versa 55 * `15` converts to `"15"`, and vice-versa 56 57 ## Complex Types 58 59 A _complex_ type is a type that groups multiple values into a single value. 60 Complex types are represented by type constructors, but several of them 61 also have shorthand keyword versions. 62 63 There are two categories of complex types: collection types (for grouping 64 similar values), and structural types (for grouping potentially dissimilar 65 values). 66 67 ### Collection Types 68 69 A _collection_ type allows multiple values of _one_ other type to be grouped 70 together as a single value. The type of value _within_ a collection is called 71 its _element type._ All collection types must have an element type, which is 72 provided as the argument to their constructor. 73 74 For example, the type `list(string)` means "list of strings", which is a 75 different type than `list(number)`, a list of numbers. All elements of a 76 collection must always be of the same type. 77 78 The three kinds of collection type in the Terraform language are: 79 80 * `list(...)`: a sequence of values identified by consecutive whole numbers 81 starting with zero. 82 83 The keyword `list` is a shorthand for `list(any)`, which accepts any 84 element type as long as every element is the same type. This is for 85 compatibility with older configurations; for new code, we recommend using 86 the full form. 87 * `map(...)`: a collection of values where each is identified by a string label. 88 89 The keyword `map` is a shorthand for `map(any)`, which accepts any 90 element type as long as every element is the same type. This is for 91 compatibility with older configurations; for new code, we recommend using 92 the full form. 93 94 Maps can be made with braces ({}) and colons (:) or equals signs (=): 95 { "foo": "bar", "bar": "baz" } OR { foo = "bar", bar = "baz" }. Quotes 96 may be omitted on keys, unless the key starts with a number, in which 97 case quotes are required. Commas are required between key/value pairs 98 for single line maps. A newline between key/value pairs is sufficient 99 in multi-line maps. 100 101 Note: although colons are valid delimiters between keys and values, 102 they are currently ignored by `terraform fmt` (whereas `terraform fmt` 103 will attempt vertically align equals signs). 104 * `set(...)`: a collection of unique values that do not have any secondary 105 identifiers or ordering. 106 107 ### Structural Types 108 109 A _structural_ type allows multiple values of _several distinct types_ to be 110 grouped together as a single value. Structural types require a _schema_ as an 111 argument, to specify which types are allowed for which elements. 112 113 The two kinds of structural type in the Terraform language are: 114 115 * `object(...)`: a collection of named attributes that each have their own type. 116 117 The schema for object types is `{ <KEY> = <TYPE>, <KEY> = <TYPE>, ... }` — a 118 pair of curly braces containing a comma-separated series of `<KEY> = <TYPE>` 119 pairs. Values that match the object type must contain _all_ of the specified 120 keys, and the value for each key must match its specified type. (Values with 121 _additional_ keys can still match an object type, but the extra attributes 122 are discarded during type conversion.) 123 * `tuple(...)`: a sequence of elements identified by consecutive whole 124 numbers starting with zero, where each element has its own type. 125 126 The schema for tuple types is `[<TYPE>, <TYPE>, ...]` — a pair of square 127 brackets containing a comma-separated series of types. Values that match the 128 tuple type must have _exactly_ the same number of elements (no more and no 129 fewer), and the value in each position must match the specified type for 130 that position. 131 132 For example: an object type of `object({ name=string, age=number })` would match 133 a value like the following: 134 135 ```hcl 136 { 137 name = "John" 138 age = 52 139 } 140 ``` 141 142 Also, an object type of `object({ id=string, cidr_block=string })` would match 143 the object produced by a reference to an `aws_vpc` resource, like 144 `aws_vpc.example_vpc`; although the resource has additional attributes, they 145 would be discarded during type conversion. 146 147 Finally, a tuple type of `tuple([string, number, bool])` would match a value 148 like the following: 149 150 ```hcl 151 ["a", 15, true] 152 ``` 153 154 ### Complex Type Literals 155 156 The Terraform language has literal expressions for creating tuple and object 157 values, which are described in 158 [Expressions: Literal Expressions](/docs/language/expressions/types.html#literal-expressions) as 159 "list/tuple" literals and "map/object" literals, respectively. 160 161 Terraform does _not_ provide any way to directly represent lists, maps, or sets. 162 However, due to the automatic conversion of complex types (described below), the 163 difference between similar complex types is almost never relevant to a normal 164 user, and most of the Terraform documentation conflates lists with tuples and 165 maps with objects. The distinctions are only useful when restricting input 166 values for a module or resource. 167 168 ### Conversion of Complex Types 169 170 Similar kinds of complex types (list/tuple/set and map/object) can usually be 171 used interchangeably within the Terraform language, and most of Terraform's 172 documentation glosses over the differences between the kinds of complex type. 173 This is due to two conversion behaviors: 174 175 * Whenever possible, Terraform converts values between similar kinds of complex 176 types if the provided value is not the exact type requested. "Similar kinds" 177 is defined as follows: 178 * Objects and maps are similar. 179 * A map (or a larger object) can be converted to an object if it has 180 _at least_ the keys required by the object schema. Any additional 181 attributes are discarded during conversion, which means map -> object 182 -> map conversions can be lossy. 183 * Tuples and lists are similar. 184 * A list can only be converted to a tuple if it has _exactly_ the 185 required number of elements. 186 * Sets are _almost_ similar to both tuples and lists: 187 * When a list or tuple is converted to a set, duplicate values are 188 discarded and the ordering of elements is lost. 189 * When a `set` is converted to a list or tuple, the elements will be 190 in an arbitrary order. If the set's elements were strings, they will 191 be in lexicographical order; sets of other element types do not 192 guarantee any particular order of elements. 193 * Whenever possible, Terraform converts _element values_ within a complex type, 194 either by converting complex-typed elements recursively or as described above 195 in [Conversion of Primitive Types](#conversion-of-primitive-types). 196 197 For example: if a module argument requires a value of type `list(string)` and a 198 user provides the tuple `["a", 15, true]`, Terraform will internally transform 199 the value to `["a", "15", "true"]` by converting the elements to the required 200 `string` element type. Later, if the module uses those elements to set different 201 resource arguments that require a string, a number, and a bool (respectively), 202 Terraform will automatically convert the second and third strings back to the 203 required types at that time, since they contain valid representations of a 204 number and a bool. 205 206 On the other hand, automatic conversion will fail if the provided value 207 (including any of its element values) is incompatible with the required type. If 208 an argument requires a type of `map(string)` and a user provides the object 209 `{name = ["Kristy", "Claudia", "Mary Anne", "Stacey"], age = 12}`, Terraform 210 will raise a type mismatch error, since a tuple cannot be converted to a string. 211 212 ## Dynamic Types: The "any" Constraint 213 214 The keyword `any` is a special construct that serves as a placeholder for a 215 type yet to be decided. `any` is not _itself_ a type: when interpreting a 216 value against a type constraint containing `any`, Terraform will attempt to 217 find a single actual type that could replace the `any` keyword to produce 218 a valid result. 219 220 For example, given the type constraint `list(any)`, Terraform will examine 221 the given value and try to choose a replacement for the `any` that would 222 make the result valid. 223 224 If the given value were `["a", "b", "c"]` -- whose physical type is 225 `tuple([string, string, string])`, Terraform analyzes this as follows: 226 227 * Tuple types and list types are _similar_ per the previous section, so the 228 tuple-to-list conversion rule applies. 229 * All of the elements in the tuple are strings, so the type constraint 230 `string` would be valid for all of the list elements. 231 * Therefore in this case the `any` argument is replaced with `string`, 232 and the final concrete value type is `list(string)`. 233 234 All of the elements of a collection must have the same type, so conversion 235 to `list(any)` requires that all of the given elements must be convertible 236 to a common type. This implies some other behaviors that result from the 237 conversion rules described in earlier sections. 238 239 * If the given value were instead `["a", 1, "b"]` then Terraform would still 240 select `list(string)`, because of the primitive type conversion rules, and 241 the resulting value would be `["a", "1", "b"]` due to the string conversion 242 implied by that type constraint. 243 * If the given value were instead `["a", [], "b"]` then the value cannot 244 conform to the type constraint: there is no single type that both a string 245 and an empty tuple can convert to. Terraform would reject this value, 246 complaining that all elements must have the same type. 247 248 Although the above examples use `list(any)`, a similar principle applies to 249 `map(any)` and `set(any)`. 250 251 If you wish to apply absolutely no constraint to the given value, the `any` 252 keyword can be used in isolation: 253 254 ```hcl 255 variable "no_type_constraint" { 256 type = any 257 } 258 ``` 259 260 In this case, Terraform will replace `any` with the exact type of the given 261 value and thus perform no type conversion whatsoever. 262 263 ## Experimental: Optional Object Type Attributes 264 265 From Terraform v0.14 there is _experimental_ support for marking particular 266 attributes as optional in an object type constraint. 267 268 To mark an attribute as optional, use the additional `optional(...)` modifier 269 around its type declaration: 270 271 ```hcl 272 variable "with_optional_attribute" { 273 type = object({ 274 a = string # a required attribute 275 b = optional(string) # an optional attribute 276 }) 277 } 278 ``` 279 280 By default, for required attributes, Terraform will return an error if the 281 source value has no matching attribute. Marking an attribute as optional 282 changes the behavior in that situation: Terraform will instead just silently 283 insert `null` as the value of the attribute, allowing the recieving module 284 to describe an appropriate fallback behavior. 285 286 Because this feature is currently experimental, it requires an explicit 287 opt-in on a per-module basis. To use it, write a `terraform` block with the 288 `experiments` argument set as follows: 289 290 ```hcl 291 terraform { 292 experiments = [module_variable_optional_attrs] 293 } 294 ``` 295 296 Until the experiment is concluded, the behavior of this feature may see 297 breaking changes even in minor releases. We recommend using this feature 298 only in prerelease versions of modules as long as it remains experimental.