Проблема

Реализуйте JavaScript функцию Array.concat используя только систему типов. Тип принимает два аргумента. Результатом должен быть новый массив, который содержит в себе объединение двух входных массивов.

Например:

type Result = Concat<[1], [2]>; // expected to be [1, 2]

Решение

Когда вы работаете с массивами в TypeScript, вариативные типы часто упрощают жизнь в моделировании нужного поведения. Они позволяют итерировать по общим тип параметрам используя ... оператор перед тип параметром.

Давайте на примере нашей же проблемы и рассмотрим вариативные типы подробнее. Мы знаем, чтобы реализовать объединение двух массивов в один на JavaScript, достаточно вернуть новый массив, в котором указать два входных с использованием ... оператора.

function concat(arr1, arr2) {
  return [...arr1, ...arr2];
}

Ключевой момент такого решения заключается в том, что используя ... оператор, мы перечисляем элементы из первого массива и включаем их в состав нашего нового массива. Те же операции делаем и со вторым входным массивом. Результатом получаем новый массив, в котором хранятся элементы из первого и второго массивов.

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

type Concat<T, U> = [...T, ...U];

Получаем ошибку “A rest element type must be an array type.”. TypeScript говорит нам, что он не может применить ... оператор к нашим тип параметрам, потому что они не массивы. Решить это можно, указав, что эти тип параметры это массивы.

type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U];

Что почитать