Skip to main content
Type expressions appear in input block field declarations. The typechecker validates that types are well-formed and that default values are type-compatible.

Primitive types

TypeDescriptionPython config accessor
stringUTF-8 stringconfig.get() / config.require()
boolBooleanconfig.get_bool() / config.require_bool()
numberInteger or floatconfig.get_float() / config.require_float()
intIntegerconfig.get_int() / config.require_int()
anyUnconstrainedconfig.require_object()
input "s" {
    name:    string
    enabled: bool   = true
    count:   int    = 1
    ratio:   number = 0.5
    meta:    any
}

Collection types

list(T)

An ordered sequence of values of type T:
azs:         list(string)
port_ranges: list(int)

set(T)

An unordered collection of unique values:
allowed_ips: set(string)

map(T)

A string-keyed map of values of type T:
tags:         map(string)
replica_info: map(number)

tuple([T1, T2, …])

A fixed-length sequence with per-position types:
endpoint: tuple([string, int])    // e.g. ["host", 5432]

Object type

A record with named, typed fields:
db_config: object({
    host: string
    port: int
    name: string
})
Object fields can themselves use any type expression.

optional(T)

Makes any type optional with a null default:
input "s" {
    extra_tags: optional(map(string))
}
With an explicit default:
input "s" {
    timeout: optional(number, 30)
}
optional(T) means the field will be null if not set; optional(T, default) means the field will be default if not set.

Named types

A dotted identifier path that names a provider-contributed or user-defined type:
input "s" {
    nat_strategy: aws.ec2.NatStrategy
    cidr:         CIDR
}
Named types parse successfully. The typechecker verifies the path is non-empty but does not resolve it against provider schemas (schema validation is handled separately). At runtime, the value is treated as any for config reading purposes.

Nested types

Types compose arbitrarily:
input "s" {
    // list of objects
    subnet_configs: list(object({
        cidr: string
        az:   string
    }))

    // map of lists
    az_map: map(list(string))

    // optional list
    extra_cidrs: optional(list(string))
}

Default value type checking

The typechecker catches obvious mismatches between default literal kinds and declared types:
MismatchError
name: string = 42default value is a number literal but field type is string
name: string = truedefault value is a boolean literal but field type is string
count: number = "30s"default value is a string literal but field type is number
count: number = truedefault value is a boolean literal but field type is number
enabled: bool = "yes"default value is a string literal but field type is bool
enabled: bool = 1default value is a number literal but field type is bool
Complex-type defaults (list, object, etc.) are not checked for full structural compatibility in the current typechecker — that is deferred to full type unification in a later phase.