Create dynamic type according to the input

Hello!
Is there a way to define a variable in Terraform whose type is determined based on the value provided, similar to the “default” keyword in JSON schema?

Hi @dvirsegev,

Terraform largely expects you to use fixed types specified directly in your configuration rather than types chosen dynamically at runtime. There are some exceptions to allow for ergonomic use of dynamic serialization formats like JSON, but you will typically have a better experience if you treat Terraform as having a static type system rather than a dynamic one.

Assuming we’re talking about module input variables (since that’s the usual place this sort of question arises) one way to model a value that could be of a few different types is to use an object type with one attribute for each type, mark them all as optional, and then add a validation rule saying that exactly one must be set:

variable "example" {
  type = object({
    t1 = optional(object({
      name = string
    }))
    t2 = optional(object({
      id = string
    }))
  })

  validation {
    condition = length({
      for v in var.example : v
      if v != null
    }) == 1
    error_message = "Must set exactly one of the top-level attributes to decide which type to use."
  }
}

This effectively uses the caller’s choice of which attribute to set as their assertion about which of the types they are intending to use, so Terraform can still type check the nested structure underneath that attribute.

Inside the module you can write logic that varies behavior based on which of the attributes is non-null, and be guaranteed (by the validation rule) that exactly one will always be set so you don’t need to worry about oddities like none of them being set or more than one being set. This is functionally a tagged union, with the chosen top-level attribute serving as the “tag” for which of the members is active.