型システム入門 — Terraformの型を理解して変数を安全に定義する

1. 概要

  • Terraformの基本型(string / number / bool)
  • コレクション型(list / set / map)
  • 構造型(tuple / object)
  • any型と型強制(type coercion)
  • variableブロックでの型制約の書き方

Terraformには独自の型システムがあります。正しい型制約を変数に設定することで、誤った値の入力を防ぎ、エラーをplan実行時に早期発見できます。


2. 基本型

説明
string文字列"ap-northeast-1"
number数値(整数・小数)42, 3.14
bool真偽値true, false
# terraform consoleで確認
> "hello"
"hello"

> 42
42

> true
true

# 型変換(型強制)
> "42" + 0
42  # 文字列→数値に自動変換

> tostring(42)
"42"

> tonumber("3.14")
3.14

> tobool("true")
true

3. コレクション型

list — 順序付きのコレクション

# list(string): 文字列のリスト
variable "availability_zones" {
  type    = list(string)
  default = ["ap-northeast-1a", "ap-northeast-1c"]
}

# インデックスアクセス
> ["a", "b", "c"][0]
"a"

# list関数
> length(["a", "b", "c"])
3

> contains(["a", "b", "c"], "b")
true

set — 順序なし・重複なしのコレクション

# set(string): 文字列のセット(重複を持てない)
variable "environments" {
  type    = set(string)
  default = ["dev", "stg", "prd"]
}

# for_eachにはsetを渡す(listはtoset()で変換)
resource "aws_s3_bucket" "env" {
  for_each = var.environments
  bucket   = "myapp-${each.key}"
}

map — キー・バリューのコレクション

# map(string): stringのmap
variable "common_tags" {
  type = map(string)
  default = {
    Environment = "dev"
    ManagedBy   = "terraform"
  }
}

# map(number): numberのmap
variable "instance_counts" {
  type = map(number)
  default = {
    web = 2
    app = 3
    db  = 1
  }
}

# キーアクセス
> {"a" = 1, "b" = 2}["a"]
1

4. 構造型

object — 複数の型を持てる固定構造

# objectは各フィールドに異なる型を持てる
variable "db_config" {
  type = object({
    instance_class    = string
    allocated_storage = number
    multi_az          = bool
    tags              = map(string)
  })
  default = {
    instance_class    = "db.t3.micro"
    allocated_storage = 20
    multi_az          = false
    tags              = { ManagedBy = "terraform" }
  }
}

tuple — 順序固定の型を持てる配列

# tupleは各位置に異なる型を持てる(objectのリスト版)
variable "port_range" {
  type    = tuple([number, number])
  default = [80, 443]
}

5. variableブロックでの型制約

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名(dev/stg/prd)"
  type        = string
  default     = "dev"

  # validationで値を制限(Terraform 0.13以降)
  validation {
    condition     = contains(["dev", "stg", "prd"], var.environment)
    error_message = "environmentはdev/stg/prdのいずれかを指定してください。"
  }
}

variable "instance_count" {
  description = "作成するEC2インスタンス数"
  type        = number
  default     = 1

  validation {
    condition     = var.instance_count >= 1 && var.instance_count <= 10
    error_message = "instance_countは1〜10の範囲で指定してください。"
  }
}

variable "enable_monitoring" {
  description = "詳細モニタリングを有効にするか"
  type        = bool
  default     = false
}

variable "subnet_ids" {
  description = "使用するサブネットIDのリスト"
  type        = list(string)
}

variable "tags" {
  description = "リソースに付与するタグ"
  type        = map(string)
  default     = {}
}

6. any型とその使いどころ

any型を使うと、どんな型の値も受け入れます。型制約を意図的に緩めたいモジュールの引数などに使いますが、乱用は避けてください。

variable "config" {
  description = "任意の設定(型を固定しない)"
  type        = any
  default     = {}
}

# ❌ anyの乱用は型チェックが効かなくなる
# ✅ 可能な限り具体的な型を指定する

any型の使いすぎに注意

any型を多用すると以下の問題が発生します。

  • 型チェックが働かず、意図しない型の値が渡されてもエラーにならない
  • 問題がterraform validateで検出されずapply時に初めてエラーが出る
  • モジュール利用者が期待する型を知る手段がなくなり可読性が低下する

通常の変数ではstring/number/list(string)/map(string)など具体的な型を指定してください。anyは意図的に型を固定しない汎用ラッパーモジュールの引数など、明確な理由がある場合のみに限定します。


7. 型変換関数

関数変換
tostring(v)任意→stringtostring(42)"42"
tonumber(v)string→numbertonumber("3.14")3.14
tobool(v)string→booltobool("true")true
tolist(v)set/tuple→listtolist(toset([1,2,3]))
toset(v)list/tuple→settoset(["a","a","b"]) → set
tomap(v)object→maptomap({a=1, b=2})

8. 関連記事


9. まとめ

  • 基本型: string / number / bool
  • コレクション型: list(順序あり)/ set(重複なし・for_each用)/ map(キー・バリュー)
  • 構造型: object(複数型の固定構造)/ tuple(位置固定の配列)
  • variableブロックで型制約(type = stringなど)を設定するとplan時に型エラーを検出できる
  • validationブロックで値の範囲・形式を制限できる
  • toset / tolist / tomapなどの型変換関数で型を変換できる

動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/expressions/types