---
title: "Constrain every element of a list"
description: "Type every element of a list with a `&:` spread, and know why a bare `[string]` does not."
source: "https://aontu.dev/how-to/constrain-list-elements/"
---

# Constrain every element of a list

Type every element of a list with a \`&:\` spread, and know why a bare \`\[string\]\` does not.

Rendered from [`docs/how-to/constrain-list-elements.md`](https://github.com/aontu-lang/aontu/blob/main/docs/how-to/constrain-list-elements.md) in the engine repository, where a correction belongs, and where the test suite executes every example on this page.

A bare `[string]` is a positional constraint: it types element 0 and says nothing about the rest. Most lists are collections, and most authors learn the difference from data that should have failed:

```aontu
tags: [string]
tags: [core 7]
```

```json
{
  "tags": [
    "core",
    7
  ]
}
```

The `7` passed because position 1 was never constrained: the two lists unified element by element, and the schema list simply ran out.

The collection form is a `&:` spread: a template unified into every element. Write this as `tags.aon`:

```aontu
tags: [&: string]
tags: [core 7]
```

Now run it:

```sh
$ aontu tags.aon
[aontu/no_scalar_unify]: Cannot unify values at path $.tags.1
...
$ echo $?
1
```

The path names the exact element, so a thousand-entry list fails at `$.tags.999`, not “somewhere in tags”.

Reach for the positional form when the positions genuinely differ (a pair, a fixed header) and for `[&: T]` whenever the list is a collection. `close` on the enclosing map seals that map’s keys and leaves the list tail open: the spread is what constrains the elements. Constraints on the list itself (`length`, `unique`) sit beside the spread with `&`; see [`length` semantics](https://aontu.dev/docs/reference-language#length-semantics).

The constructs are specified in the language reference under [Lists](https://aontu.dev/docs/reference-language#lists) and [Spreads `&:`](https://aontu.dev/docs/reference-language#spreads-). To close the map around the list too, see [forbid unexpected keys](https://aontu.dev/how-to/forbid-unexpected-keys); a bare-kind element template also crosses to JSON Schema as `items`: see [export JSON Schema](https://aontu.dev/how-to/export-json-schema).
