A module accepts a bucket_config input with name, retention_days and versioning. Callers must always set name, and should be able to omit retention_days and versioning and receive 30 and true, while Terraform still type-checks every attribute. How should the variable type be declared?
Select an answer to reveal the explanation.
Short Explanation
optional() is how you write "you can skip this field and here's what you get if you do" right into the type. A whole-variable default doesn't help, because the moment a caller passes any object, your default is gone.
Full Explanation
Object type constraints can mark individual attributes as optional with the optional modifier, and its second argument supplies a default for that attribute when the caller omits it. Declaring name as a required string and retention_days and versioning as optional with defaults of 30 and true makes the contract explicit: Terraform enforces the type of every attribute, requires name, and fills in the defaults, all visible in the module's documentation. A variable-level default applies only when the caller passes nothing at all; as soon as a caller supplies an object, the whole default is replaced, and an object missing required attributes fails type conversion. Using map(any) gives up structural type checking, since all values must share one type and attribute names are not checked, and pushes defaulting logic into locals that callers cannot see in the interface. The nullable argument applies to the variable as a whole and controls whether null is accepted; it neither makes object attributes optional nor supplies per-attribute defaults. Exam caveat: optional attribute defaults apply when the attribute is omitted or set to null, so document that null means use the default. Operational check: write a test that passes only name and asserts the resulting retention and versioning values equal 30 and true.