Tuple

Tuple представляет собой структуру данных с заранее известным количеством элементов, где каждый элемент имеет строго определённый тип и порядок. В отличие от массивов, допускающих произвольную длину, tuple описывает фиксированную последовательность значений, что делает его особенно полезным для моделирования строго типизированных наборов данных.


Базовое определение tuple

В Superstruct tuple создаётся через функцию tuple, принимающую набор структур:

import { tuple, string, number, boolean } from 'superstruct'

const Point = tuple([number(), number()])

В данном примере описана структура двумерной точки, где:

  • первый элемент — число (координата X),
  • второй элемент — число (координата Y).

Проверка данных с tuple

Использование tuple для валидации позволяет гарантировать точное соответствие формы данных:

import { assert } from 'superstruct'

assert([10, 20], Point) // валидно
assert([10], Point)     // ошибка
assert([10, 20, 30], Point) // ошибка

Tuple строго проверяет не только типы, но и количество элементов.


Принцип строгой позиции элементов

Ключевая особенность tuple — позиционная типизация. Каждый индекс массива соответствует конкретному типу:

const UserRecord = tuple([
  string(),  // имя
  number(),  // возраст
  boolean()  // активен ли пользователь
])

Пример корректных данных:

['Alex', 28, true]

Любое отклонение от порядка или типов приводит к ошибке:

['Alex', true, 28] // нарушение порядка типов

Вложенные tuple

Tuple может включать другие tuple, формируя сложные структуры данных:

const Point3D = tuple([number(), number(), number()])

const Line = tuple([
  Point3D,
  Point3D
])

Данные:

[
  [0, 0, 0],
  [10, 10, 10]
]

Такая модель часто используется в графике, геометрии и математических вычислениях.


Комбинирование tuple с другими структурами

Tuple может содержать любые структуры Superstruct, включая object, array, union:

import { object, tuple, string, number } from 'superstruct'

const Response = tuple([
  number(),
  object({
    status: string(),
    message: string()
  })
])

Пример валидных данных:

[
  200,
  {
    status: 'ok',
    message: 'success'
  }
]

Использование tuple в функциях валидации

Tuple часто применяется при строгой проверке входных параметров:

import { create } from 'superstruct'

const Config = tuple([
  string(),
  number()
])

function init(config) {
  const [name, timeout] = create(config, Config)

  return {
    name,
    timeout
  }
}

Здесь гарантируется, что входные данные всегда соответствуют ожидаемой сигнатуре.


Поведение при ошибках валидации

При несоответствии структуры Superstruct формирует детализированную ошибку:

import { validate } from 'superstruct'

const [error, result] = validate(['test'], tuple([string(), number()]))

error будет содержать информацию о:

  • недостатке элементов,
  • несоответствии типов,
  • позиции ошибки в tuple.

Опциональные элементы в tuple

Хотя tuple ориентирован на фиксированную длину, можно использовать optional для частичной гибкости:

import { optional, tuple, string, number } from 'superstruct'

const Flexible = tuple([
  string(),
  optional(number())
])

Допустимые значения:

['name']
['name', 123]

При этом порядок элементов остаётся строго фиксированным.


Tuple как замена объектам в компактных структурах

Tuple часто применяется вместо объектов, когда важна компактность и позиционная семантика:

// объектный вариант
{
  x: 10,
  y: 20
}

// tuple вариант
[10, 20]

Преимущества tuple:

  • меньший размер данных,
  • ускоренная сериализация,
  • строгая позиционная модель.

Недостатки:

  • потеря именованных полей,
  • зависимость от порядка элементов.

Использование tuple в API контракте

Tuple удобен для описания контрактов, где важна строгая сигнатура:

const HttpResponse = tuple([
  number(),   // статус код
  string(),   // тело ответа
  boolean()   // флаг кеширования
])

Такая модель фиксирует структуру ответа без двусмысленности.


Сравнение tuple и array в Superstruct

Обычный массив:

array(number())
  • произвольная длина
  • одинаковый тип элементов

Tuple:

tuple([number(), string()])
  • фиксированная длина
  • разные типы по позициям

Типичные сценарии применения

Tuple наиболее уместен в случаях:

  • координатные системы (2D, 3D и выше),
  • RGB/HSV представления цвета,
  • сигнатуры функций,
  • сериализация компактных структур,
  • бинарные или протокольные данные.

Пример RGB:

const RGB = tuple([
  number(), // R
  number(), // G
  number()  // B
])

Ограничения модели tuple

Несмотря на гибкость Superstruct, tuple сохраняет строгие ограничения:

  • невозможность динамического изменения длины,
  • жёсткая зависимость от порядка элементов,
  • отсутствие именованных полей,
  • необходимость точного соответствия структуры.

Эти ограничения являются частью его концепции строгой типизации данных на уровне рантайма.