TL;DR

Terraform’s ternary operator converts integers to strings when constructing objects. Use the array index pattern to preserve integer types.

Solution: Use array index pattern — [value_if_true, value_if_false][condition ? 0 : 1]

The Problem

Direct ternary — converts int to string:

output "with_ternary_try" {
  value = condition ? {
    deadLetterTargetArn = "arn:aws:sqs:us-west-2:12345678:test-queue"
    maxReceiveCount = 1  # Input: integer 1
  } : {}
}
# Result: maxReceiveCount = "1" (STRING!)

Array index pattern — preserves int:

output "with_array_index_pattern" {
  value = [{
    deadLetterTargetArn = "arn:aws:sqs:us-west-2:12345678:test-queue"
    maxReceiveCount = 1  # Input: integer 1
  }, {}][condition ? 0 : 1]
}
# Result: maxReceiveCount = 1 (INTEGER!)

Why It Happens

Terraform performs type unification across both branches of a ternary operator. When comparing {maxReceiveCount = 1} with {}, it converts the integer to a string for consistency.

The array index pattern avoids this by constructing objects first, then selecting via index — no cross-branch type unification occurs.

When to Use Array Index Pattern

  • AWS API parameters requiring integers (SQS maxReceiveCount, Lambda timeouts, DynamoDB capacity)
  • Any scenario where type preservation is critical
  • Passing values to modules with strict type requirements

Example

test.tf

variable "instance" {
  type = any
  default = {}
}

# Direct ternary - converts int to string:
output "with_ternary_try" {
  value = try(var.instance.test, null) == null ? {
    deadLetterTargetArn = "arn:aws:sqs:us-west-2:12345678:test-queue"
    maxReceiveCount = 1  # Input: integer 1
  } : {}
}
# Result: maxReceiveCount = "1" (STRING!)

# Array index pattern - preserves int:
output "with_array_index_pattern" {
  value = [{
    deadLetterTargetArn = "arn:aws:sqs:us-west-2:12345678:test-queue"
    maxReceiveCount = 1  # Input: integer 1
  }, {}][try(var.instance.test, null) == null ? 0 : 1]
}
# Result: maxReceiveCount = 1 (INTEGER!)

TF Plan Output

 terraform plan

Changes to Outputs:
  + with_array_index_pattern = {
      + deadLetterTargetArn = "arn:aws:sqs:us-west-2:12345678:test-queue"
      + maxReceiveCount     = 1
    }
  + with_ternary_try         = {
      + deadLetterTargetArn = "arn:aws:sqs:us-west-2:12345678:test-queue"
      + maxReceiveCount     = "1"
    }

You can apply this plan to save these new output values to the
Terraform state, without changing any real infrastructure.