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.