# Типы данных в HCL: string, number, list, map, object _Основы Terraform · TerraformLab Knowledge Base_ **TL;DR:** HCL поддерживает примитивы (string, number, bool) и сложные типы: list, set, map, tuple, object. Эта статья, про синтаксис каждого и про разницу между похожими (list vs tuple, map vs object): meta_description: "Типы данных HCL: string, number, bool, list, set, map, tuple, object. Что выбрать для variable, где разница между list и tuple, синтаксис каждого с примерами." ## Примитивные типы Базовых типов три: | Тип | Литерал | Пример | |-----|---------|--------| | `string` | в двойных кавычках | `"us-east-1"` | | `number` | целое или дробное | `42`, `3.14` | | `bool` | `true` / `false` | `true` | В переменных тип объявляется явно: ```hcl variable "region" { type = string default = "us-east-1" } variable "retention_days" { type = number default = 30 } variable "enable_versioning" { type = bool default = false } ``` ## Сложные коллекционные типы Collection, это «много одинакового». Все элементы одного типа. ### list (упорядоченный) ```hcl variable "az_names" { type = list(string) default = ["us-east-1a", "us-east-1b", "us-east-1c"] } ``` Обращение по индексу: `var.az_names[0]` → `"us-east-1a"`. Порядок важен и стабилен. ### set (без порядка, без дубликатов) ```hcl variable "allowed_cidrs" { type = set(string) default = ["10.0.0.0/8", "192.168.0.0/16"] } ``` Порядка нет, по индексу не обратишься. Используется с `for_each`, там как раз нужны уникальные ключи без порядка. ### map (ключ-значение, ключи строковые) ```hcl variable "tags" { type = map(string) default = { Environment = "dev" Owner = "platform" } } ``` Обращение по ключу: `var.tags["Environment"]` → `"dev"`. Все значения одного типа (`string` в этом примере). ## Структурные типы Structural, это «много разного, заранее известной формы». ### object (поля разных типов) ```hcl variable "bucket_settings" { type = object({ name = string versioning = bool retention_days = number }) default = { name = "my-bucket" versioning = true retention_days = 90 } } ``` Поля могут быть разных типов. Обращение через точку: `var.bucket_settings.name`. Если в дефолте указать не все поля или лишние, terraform упадёт на `validate`. ### tuple (упорядоченная пара/тройка) ```hcl variable "name_and_size" { type = tuple([string, number]) default = ["primary", 100] } ``` Tuple, это как list, но каждый элемент своего типа, фиксированной длины. На практике почти не нужен: для понятности обычно лучше object. ## Чем `list` отличается от `tuple` - `list(T)`, любое количество элементов одного типа `T`. - `tuple([T1, T2, T3])`, ровно три элемента, каждый своего типа. Если коллеги пишут одно и то же, это list. Если структура с несколькими полями, object предпочтительнее, чем tuple. ## Чем `map` отличается от `object` - `map(T)`, произвольное количество ключей, все значения типа `T`. - `object({...})`, фиксированный набор ключей, каждое значение своего типа. Tag set, это `map(string)`. Конфиг ресурса, `object({...})`. Простой эвристический способ: если ключи приходят снаружи (от пользователя, не из кода). `map`; если ты сам пишешь имена ключей, `object`. ## `any`, отказ от типизации ```hcl variable "anything" { type = any } ``` Terraform не проверит структуру вообще. Это лазейка для случаев, когда тип меняется в runtime, и она почти всегда, анти-паттерн. Если используешь `any`, в комментарии пиши, почему точно нельзя было типизировать. ## Optional поля в object С Terraform 1.3+ поля object можно делать необязательными: ```hcl variable "logging" { type = object({ enabled = bool target_arn = optional(string) prefix = optional(string, "logs/") # default }) default = { enabled = true } } ``` - `optional(string)`, поле можно не указывать, значение будет `null`. - `optional(string, "logs/")`, значение по умолчанию. Это спасает от длинных object-схем, где половина полей нужна редко. ## Подводные камни - **`null` ≠ отсутствие поля.** В object с обязательными полями нужно передать все, даже `null` явно. - **`map(string)` против `object({a=string})` в variable.** При `map(string)` ключи могут быть любые; при `object`, только перечисленные. - **Set теряет порядок.** Если важен порядок (например, в outputs): переключайся на list. - **Числа в HCL, без точности.** terraform внутри хранит число как `cty.Number` (BigFloat). На больших значениях возможно округление, но обычно это не проблема. - **Boolean из строки.** `"true"` (строка) и `true` (bool): разные типы. terraform не приводит автоматически, будет ошибка типа. ## Команды ```bash terraform console ``` Интерактивная REPL для проверки типов. Введи туда `type(var.tags)` чтобы увидеть распознанный тип. ```bash echo 'type(var.tags)' | terraform console ``` Не-интерактивный вариант: распечатать тип одной переменной. ```bash terraform validate ``` Проверяет соответствие default-значений объявленным типам, без обращения к облаку. ## См. также - [HCL: язык, на котором пишут Terraform](/terraform/kb/hcl-syntax.md) - [Блок provider: кому Terraform будет звонить](/terraform/kb/tf-provider-block.md) - [Version constraints в Terraform: required_version и провайдеры](/terraform/kb/tf-version-constraints.md)