Что такое tuple в TypeScript?
Определение
Tuple (кортеж) в TypeScript — это специальный вид типа массива, который описывает фиксированное количество элементов с точно заданными типами для каждой позиции. Если обычный массив T[] описывает произвольное количество однородных элементов, то кортеж фиксирует и длину, и тип каждого элемента отдельно.
Синтаксис
Кортеж объявляется через квадратные скобки, где типы перечислены в нужном порядке:
let point: [number, number] = [10, 20];
let entry: [string, number] = ["age", 30];
В отличие от number[], здесь TypeScript будет проверять не только тип, но и позицию, и количество элементов. Попытка добавить лишний элемент через присваивание или несоответствие порядка вызовет ошибку компиляции.
Отличие от обычного массива
let arr: number[] = [1, 2, 3, 4]; // любое количество number
let tuple: [number, string] = [1, "a"]; // строго два элемента разных типов
tuple = [1, "a", 2]; // ошибка: слишком много элементов
tuple = ["a", 1]; // ошибка: перепутан порядок типов
Важный нюанс: под капотом в JS кортеж — это обычный массив, TypeScript лишь добавляет статическую проверку типов на этапе компиляции, во время выполнения никакой разницы нет.
Именованные элементы (labeled tuples)
Начиная с TypeScript 4.0 элементы кортежа можно подписывать для читаемости, особенно полезно для параметров функций:
function useState<T>(initial: T): [state: T, setState: (value: T) => void] {
// реализация хука
return [initial, () => {}];
}
Метки не влияют на типизацию, а только на подсказки в IDE.
Опциональные и rest-элементы
Кортежи поддерживают необязательные элементы (?) и rest-элементы (...), что позволяет описывать переменную длину с сохранением строгих типов на фиксированной части:
type Pair = [name: string, age?: number];
type StringsThenNumbers = [string, ...number[]];
const p1: Pair = ["Tom"];
const p2: Pair = ["Tom", 25];
const mix: StringsThenNumbers = ["a", 1, 2, 3];
readonly-кортежи
Чтобы запретить мутацию элементов кортежа (push, изменение по индексу), используют модификатор readonly:
const rgb: readonly [number, number, number] = [255, 0, 0];
rgb[0] = 100; // ошибка: readonly
rgb.push(1); // ошибка: метод push недоступен у readonly-кортежа
Где применяются
- Возвращаемые значения функций/хуков, где важна позиция, а не имя поля (классический пример —
useStateиз React, возвращающий[value, setValue]). - Пары «ключ-значение» при переборе
Object.entries. - Работа с координатами, диапазонами, RGB-цветами — везде, где фиксирован порядок и тип разных по смыслу значений.
- Как альтернатива объекту, когда порядок важнее именования и нужна максимально компактная запись.
Что хочет услышать интервьюер
Понимание, что tuple — это массив фиксированной длины с типами, заданными для каждой позиции
Умение объяснить отличие от обычного массива (`T[]`) на конкретном примере
Знание про readonly-кортежи и их применение для иммутабельности
Знание опциональных (`?`) и rest-элементов в кортежах
Понимание, что на уровне JS кортеж — обычный массив, различие существует только на уровне типов
Пример: Базовый пример tuple
let point: [number, number] = [10, 20];
// ошибка: неверный порядок и лишний элемент
// point = ["10", 20, 30];
function useState<T>(initial: T): [state: T, setState: (value: T) => void] {
let value = initial;
const setValue = (next: T) => { value = next; };
return [value, setValue];
}
const [count, setCount] = useState(0);
setCount(5);
Пример: readonly и rest-элементы
// неизменяемый кортеж
const rgb: readonly [number, number, number] = [255, 0, 0];
// rgb[0] = 100; // ошибка компиляции
// кортеж с необязательным элементом
type Pair = [name: string, age?: number];
const p1: Pair = ["Tom"];
const p2: Pair = ["Tom", 25];
// кортеж с rest-элементами
type StringsThenNumbers = [string, ...number[]];
const mix: StringsThenNumbers = ["a", 1, 2, 3];
Типичные ошибки
Путают tuple с интерфейсом/объектом и не могут объяснить, зачем нужен именно порядок элементов
Не знают, что кортежи можно делать readonly для защиты от мутаций
Забывают, что TypeScript проверяет типы кортежей только статически — в рантайме это обычный массив без ограничений
Не могут привести практический пример использования (например, `useState` в React или `Object.entries`)
Не знают про опциональные и rest-элементы, из-за чего считают, что кортежи всегда строго фиксированной длины


