Defaults function usage with object-type variable with optional field

I’m currently using (and enjoying) the module_variable_optional_attrs experiment to allow me to define a variable with an optional field, like so:

variable "foo" {
  type = object({
    bar        = optional(string)
  })
}
locals {
  foo = defaults(var.foo, {
    bar        = ""
  })
}

It seems that once you use defaults like so, you then need to reference the value via local instead of var:

resource "pseudo_resource" {
  bar = local.foo.bar
}

While I now understand that this feature appears to be making use of the existing locals logic, it is somewhat confusing since the initial goal is to define a default for an optional variable.

Just wondering if there is a plan (or if it’s even possible) to add the defaults logic to variable definitions at some point?

I’m shooting for something like:

resource "pseudo_resource" {
  bar = var.foo.bar
}

Since otherwise we have to keep which variables we’ve defaulted vs not correct when building modules.

If there is a better place for this question, please let me know.

Thanks!

I don’t know if there is a better place for feedback on experimental features either. I’ll add my though here in the hope that it garners a bit more discussuion.

So, could I suggest that when I add an optional field to an object I also could specify the default value as per below? The currently experimental default function effectively requires me to use a local for any case where I am going to use the variable multiple times and while it might ultimately be more flexible it is neither intuitive nor elegant. I just could not bring myself to use the feature in its current form in my code.

variable "subnets" {
  description = "The set of subnets that are to be created."
  type = map(object({
  cidr_newbits = string
  cidr_netnum = string
  service_endpoints = set(string)
  route_to_firewall = optional(bool, true)
}))
default = {}
}

It keeps the defaults together and allows modules to be changed with minimal effort to retain full backward compatibility with the previous functionality.

Just tossing my hat in - i agree. defaults value should persist:

objects with optional attributes and defaults should use default when not set explicitly instead of null

variable "myvar" {
  type = object({
    name = string
    age  = optional(string)
  })
  default = {
    name = "john deere"
    age = "none ya business"
  }
}

output "myvar" {
 value = var.myvar
}
$ terraform apply -var myvar={\"name\"=\"drew\"}
...
Outputs:

myvar = {
  "age" = tostring(null)
  "name" = "drew"
}