Terraform variable type difference on `type=any` vs `type=map`?

When I define variable type like

variable hello {
type=any
defalt={}
}

The following yaml file can works as input to the variable without problem.

hello:
hello1:
yaml_file: “hello1.yaml”
hello2:
json_file: “hello2.json”
hello3:
text_file: “hello3.txt”

But when I set the variable type as:

variable hello {
type = map
default = {}
}

it will fails with error message: … attribute types must all match for conversion to map.

Please help

Hi @dcopperfield888,

When you declare any you should understand that as “Terraform should infer which type to use automatically based on the given value”.

In your example, I expect Terraform inferred the following type:

object({
  hello1 = object({
    yaml_file = string
  })
  hello2 = object({
    json_file = string
  })
  hello3 = object({
    text_file = string
  })
})

However, if you write type = map then that’s a legacy shorthand for type = map(any), so you’ve then constrained Terraform to use a map and to only infer which element type to use for that map. Terraform then tries to convert the object type above into a map type, but cannot do so automatically because each of the elements has a different object type, and so there is no single type that Terraform could replace any with during inference.

A third alternative, which I think is the best compromise here, is to explain to Terraform which nested attributes are expected explicitly, like this:

  type = map(object({
    yaml_file = optional(string)
    json_file = optional(string)
    text_file = optional(string)
  })

This example doesn’t include any at all, so there is nothing to infer. Terraform would be able to convert the structure from your YAML document into a value of this type, where each of the attributes will either be the string specified in the YAML, or null for each attribute that was not specified.

The any placeholder is intended only for situations where a module is accepting an arbitrary data structure and passing it verbatim – without any further processing – to a remote system. It’s not intended as a way to just skip specifying the type constraint that your module is relying on.