Типизируйте spread, который дописывает элемент в кортеж и сливает два объекта
Напишите два помощника.
prepend принимает значение и кортеж и возвращает новый кортеж с этим значением впереди. Результат должен иметь тип [H, ...T] — каждая исходная позиция сохраняет свой тип, — а не (H | T[number])[].
merge принимает два объекта и возвращает их spread. Ключ, присутствующий в обоих, должен получить тип из второго объекта — ровно так, как ведёт себя spread во время выполнения.
Ограничения: без any, без Function, без утверждений типа.
export function prepend<H, T extends unknown[]>(head: H, tail: T) {
// ваш код здесь
}
export function merge<A extends object, B extends object>(a: A, b: B) {
// ваш код здесь
}
Допишите реализацию.
Rest-элемент сохраняет позиции: тип [H, ...T] у prepend держит каждый индекс, а обычный массив даёт лишь T[]. Spread объектов перезаписывает, ровно как в рантайме: ключ, присутствующий в обоих, берёт тип второго объекта. Без any и без утверждения типа.
- ✗Аннотировать результат prepend массивом объединения, выбрасывая все позиции
- ✗Ждать, что общий ключ возьмёт тип из первого объекта, а не из второго
- ✗Брать утверждение типа, чтобы вернуть кортеж, вместо rest-элемента в типе возврата
- →Что теряется при spread обычного массива вместо кортежа?
- →Почему spread двух обобщённых параметров даёт
A & B, а не форму с перезаписью?
Кортеж сохраняет позиции только через rest-элемент в типе возврата; вывод сам по себе расширит литерал массива до (H | T[number])[].
export function prepend<H, T extends unknown[]>(head: H, tail: T): [H, ...T] {
return [head, ...tail];
}
export function merge<A extends object, B extends object>(a: A, b: B) {
return { ...a, ...b }; // выводится как A & B
}
const t = prepend('id', [1, true] as const); // [string, 1, true]
const m = merge({ n: 1 }, { n: 'x' }); // n берётся из второго объекта
со своим типом. Обычный массив такой информации не несёт: spread T[] даёт снова T[].
побеждает второй объект, ровно как в рантайме. Для обобщённых A/B он не может знать ключи заранее и выдаёт A & B; аннотировать A | B было бы неверно — результат содержит ключи обоих, а не одного из них.
- Кортеж.
[H, ...T]— это tuple с rest-элементом: каждая позицияTостаётся на месте и - Объекты. Для конкретных типов компилятор вычисляет форму с перезаписью — на общем ключе