1. 概要
toset— listやtupleをset型に変換するtolist— setやtupleをlist型に変換するtomap— objectをmap型に変換する- 型変換が必要な場面と
for_eachとの関係
Terraformの型システムでは、set・list・mapは似ているようで異なります。for_eachはset/mapしか受け付けないため、listを渡すときはtosetが必要です。
2. toset — listをsetに変換する
toset(list)は、listをsetに変換します。setは順序がなく、重複を持てない型です。
# terraform consoleで確認
> toset(["dev", "stg", "prd"])
toset([
"dev",
"prd",
"stg",
])
# 重複は自動的に排除される
> toset(["dev", "stg", "dev", "prd"])
toset([
"dev",
"prd",
"stg",
])
for_eachにlistを渡すにはtosetが必要
# ❌ for_eachにlistは渡せない
resource "aws_s3_bucket" "env" {
for_each = ["dev", "stg", "prd"] # Error: for_each supports sets and maps
bucket = "myapp-${each.key}"
}
# ✅ tosetでsetに変換してから渡す
resource "aws_s3_bucket" "env" {
for_each = toset(["dev", "stg", "prd"])
bucket = "myapp-${each.key}"
tags = {
Name = "myapp-${each.key}"
Environment = each.key
ManagedBy = "terraform"
}
}
tosetを使う完全な例
terraform {
required_version = ">= 1.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
variable "environments" {
description = "作成する環境名のリスト"
type = list(string)
default = ["dev", "stg", "prd"]
}
resource "aws_s3_bucket" "env_bucket" {
# variableはlist型なのでtosetで変換
for_each = toset(var.environments)
bucket = "myapp-${each.key}-assets"
tags = {
Name = "myapp-${each.key}-assets"
Environment = each.key
ManagedBy = "terraform"
}
}
3. tolist — setをlistに変換する
tolist(set)は、setをlistに変換します。順序が保証されない点に注意が必要です。
# terraform consoleで確認
> tolist(toset(["c", "a", "b"]))
["a", "b", "c"] # アルファベット順に並び替えられる(保証はされない)
インデックスアクセスに使う
setはインデックスアクセスができないため、特定の要素が必要なときはtolistで変換します。
data "aws_availability_zones" "available" {
state = "available"
}
# setはインデックスアクセスできないのでtolistに変換
locals {
first_az = tolist(data.aws_availability_zones.available.names)[0]
second_az = tolist(data.aws_availability_zones.available.names)[1]
}
resource "aws_subnet" "primary" {
vpc_id = aws_vpc.main.id
availability_zone = local.first_az
cidr_block = "10.0.1.0/24"
tags = {
Name = "primary-subnet"
ManagedBy = "terraform"
}
}
4. tomap — objectをmapに変換する
tomap(object)は、objectをmap型に変換します。objectはキーと値の型が固定ですが、mapは同じ値型の任意のキーを持てます。
# terraform consoleで確認
> tomap({ name = "web", port = 80 })
{
"name" = "web"
"port" = "80" # 数値も文字列に統一される(mapは同一型)
}
型制約でmapを明示する
variable "tags" {
description = "リソースに付与するタグ"
type = map(string)
default = {
Environment = "dev"
ManagedBy = "terraform"
}
}
resource "aws_s3_bucket" "main" {
bucket = "myapp-main"
tags = merge(var.tags, {
Name = "myapp-main"
})
}
5. list / set / map の違いまとめ
| 型 | 順序 | 重複 | インデックスアクセス | for_each | 用途 |
|---|---|---|---|---|---|
list | あり | 可 | list[0] | ❌(tosetが必要) | 順序付きのコレクション |
set | なし | 不可 | ❌ | ✅ | 重複なし、for_eachに渡す |
map | なし | 値は可 | map["key"] | ✅ | キー→値の対応 |
6. よくある間違い
for_eachにlist変数を直接渡す
variable "bucket_names" {
type = list(string)
default = ["bucket-a", "bucket-b"]
}
# ❌ listはfor_eachに渡せない
resource "aws_s3_bucket" "this" {
for_each = var.bucket_names # Error!
bucket = each.value
}
# ✅ tosetで変換する
resource "aws_s3_bucket" "this" {
for_each = toset(var.bucket_names)
bucket = each.key
}
setに対してインデックスアクセスする
# ❌ setはインデックスアクセスできない
output "first_subnet" {
value = aws_subnet.this.*.id[0] # setに[0]は使えない
}
# ✅ tolistに変換してからアクセスする
output "first_subnet" {
value = tolist(values(aws_subnet.this))[0].id
}
7. 関連記事
- for_each — map/setで動的にリソースを作成するメタ引数 — tosetが必要な理由
- 型システム入門 — Terraformの型を理解する — list/set/map/object の詳細
- for式の使い方 — setやmapを変換する
- merge / concat / flatten の使い方 — listを組み合わせる関数
- 型制約の詳細 — object/tuple/optional/any
- length / keys / values / contains — コレクション検査
8. まとめ
toset(list)— listをsetに変換。重複を排除。for_eachにlistを渡すときに必須tolist(set)— setをlistに変換。インデックスアクセスが必要なときに使うtomap(object)— objectをmapに変換。値型が統一されるfor_eachはset/mapしか受け付けないため、list変数を持つ場合はtosetで変換する
動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/functions/toset