Мне нужно ввести функцию, которая принимает кортеж и выводит его сопоставленную версию
в качестве первой попытки я определил кортеж идентификаторов, который возвращает кортеж того же типа
declare const tupleIdentity: <Tup extends readonly any[]>(tup: Tup) => Tup
const [a, b, c, d] = tupleIdentity([1, 's', 3]) // a:number, b:string, c:number, d:undefined
отлично, он отслеживает длину кортежа и типы элементов!
но не смог найти типизацию, возвращающую сопоставленную версию кортежа
например объект, обертывающий каждый элемент
// a naive attempt :
type Wrap<T> = { wrapped: T }
declare const tupleMapper: <Tup extends readonly any[]>(tup: Tup)
=> Tup extends Array<infer T> ? Wrap<T>[] : never
const [x, y, z] = tupleMapper([1, 's', 3]) // x,y,z: Wrap<string | number> | undefined
может ли система типов Ts объявить такую типизацию?






Давайте сначала немного изменим функцию сопоставления:
declare const map: <T extends ReadonlyArray<unknown>>(tuple: T) => MapTuple<T>;
Он берет любой кортеж, а затем передает этот кортеж типу MapTuple, где происходит настоящее волшебство.
И вот оно:
type MapTuple<T, R extends ReadonlyArray<unknown> = []> =
T extends readonly [infer First, ...infer Rest]
? MapTuple<Rest, [...R, Wrap<First>]> : R;
Мы получаем первый элемент T, а также остальные как еще один кортеж.
Если он не может вывести их, то кортеж пуст, поэтому мы возвращаем результат R.
Однако, если это так, мы сопоставляем оставшиеся элементы и добавляем к результату обернутый первый элемент.
Это в основном цикл, отображающий каждый элемент.
Вы можете объявить тип, используя сопоставленный тип (который дает кортеж при применении к типу кортежа):
type Wrap<T> = { wrapped: T }
declare const tupleMapper: <Tup extends readonly any[]>(tup: Tup) =>
{[K in keyof Tup]: Wrap<Tup[K]>}
const [x, y, z] = tupleMapper([1, 's', 3]) // [Wrap<number>, Wrap<string>, Wrap<number>]
// x: Wrap<number>
// y: Wrap<string>
// z: Wrap<number>
хорошо, спасибо! Я не знал, что компилятор Ts неявно приводит сопоставленный тип к кортежу/массиву при применении к кортежам/массивам!
Это очень интересное и поучительное рабочее решение, спасибо! Однако я решил пометить решение @Oblosys, так как оно кажется более простым.