Terraform Curriculum
Hcl Types
Every value in HCL has a type. Understanding types is important because:
- Terraform validates that you are passing the right type of value to each argument
- Variables have types that determine what values they accept
- Some functions only work with specific types
- Type mismatches cause clear error messages during
terraform validateorterraform plan
HCL has two categories of types: primitive types (simple single values) and complex types (collections of values).
Primitive Types
Primitive types hold a single value. There are three primitive types in HCL.
string
A string is a sequence of characters — text. Strings are always written inside double quotes.
String interpolation — embed expressions inside strings using ${}:
Multi-line strings — use heredoc syntax for strings that span multiple lines:
The <<-EOF syntax allows indentation inside the heredoc — the leading whitespace is stripped. The EOF marker must appear on its own line and marks the end of the string.
number
A number represents a numeric value. It can be an integer or a decimal.
Numbers in HCL do not use quotes:
Some arguments expect a number. If you pass a string, Terraform may convert it automatically (implicit conversion), but it is best practice to use the correct type.
bool
A boolean represents a true or false value. In HCL, booleans are written as true or false without quotes.
Common mistakes with booleans:
Complex Types
Complex types hold multiple values. There are two main categories: collection types and structural types.
Collection Types
Collection types group multiple values of the same type together.
list
A list is an ordered sequence of values. Lists are written inside square brackets []. The values must all be the same type.
Accessing list elements — use index (starting from 0):
Using lists in resources:
Common list operations:
set
A set is similar to a list but:
- Values are unordered — you cannot guarantee what order they appear in
- Values must be unique — no duplicates allowed
Sets are useful when the order does not matter and you want uniqueness enforced. Many AWS resource arguments that appear to be lists are actually sets internally. Use toset() to convert a list to a set:
map
A map is a collection of key-value pairs where all values are the same type. Maps are written inside curly braces {}.
Accessing map values — use the key:
Common map uses — tags:
Structural Types
Structural types hold values of different types in a defined structure.
object
An object is a collection of named attributes, each with its own type. Unlike a map (where all values must be the same type), an object can have different types for each attribute.
Objects are useful for grouping related configuration together into a single variable rather than having many separate variables.
tuple
A tuple is an ordered sequence of values where each position has a specific type. Tuples are less commonly used in Terraform than the other types.
In practice, it is usually clearer to use an object instead of a tuple because object attributes have names.
The any Type
The any type is a special type that tells Terraform to accept any type of value. It skips type checking.
Use any sparingly. It removes the protection that type checking provides. It is occasionally useful when writing flexible modules that need to accept values of different shapes, but for most variables, specify the exact type.
Type Conversion
Terraform can automatically convert between compatible types in some cases. This is called implicit type conversion.
You can also explicitly convert types using built-in functions:
Type Constraints in Variables
When you declare a variable, the type argument sets a type constraint. Terraform will validate that any value passed for that variable matches the constraint.
Real-World Example Using Multiple Types
Here is a realistic Terraform configuration that uses several different types together:
Summary
- Primitive types:
string(text),number(numeric),bool(true/false) - Collection types:
list(ordered, same type),set(unordered, unique, same type),map(key-value pairs, same value type) - Structural types:
object(named attributes with different types),tuple(ordered with positional types) anytype skips type checking — use sparingly- Type constraints in variables help catch errors early and make modules self-documenting
- Use explicit conversion functions (
tostring,tonumber,tobool,toset,tolist,tomap) when you need to convert between types - Complex types like
list(object({...}))are very powerful for configuring groups of similar resources
In the next chapter, we cover variables in depth — how to declare them, set values, use them in configurations, and validate them.