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.