выводить общие параметры в типе остальных кортежей - PullRequest
0 голосов
/ 25 сентября 2019

Чтение о остальных элементах в типах кортежей и попытка выяснить, как извлечь обобщенную часть типа:

type Attribute<Type> = { id: string, type?: Type };

type Position = { x: number, y: number };
let Position: Attribute<Position> = { id: "position" };

type Status = "active" | "inactive";
let Status: Attribute<Status> = { id: "status" };

Я уверен, что есть способ написатьусловный тип, который отобразит кортеж с различными Attribute<T> на кортежи с различными T.

type AttributeTypes<Attributes extends Attribute<any>[]> =
   Attributes extends Attribute<infer T> ? T[] : never;

type Result = AttributeTypes<[typeof Position, typeof Status]> // should be `[Position, Status]`

Но я недостаточно хорошо понимаю этап вывода, и он всегда заканчивается в never branch.

Последним шагом будет написание функции, которая использует выведенные типы как часть возврата ( Playground ):

function getAll<Attributes extends Attribute<any>[]>(
  ...attributes: Attributes
): AttributeTypes<Attributes> {
  return attributes.map(attribute => attribute.type);
}

let [position, status]: [Position, Status] = getAll(Position, Status);

1 Ответ

2 голосов
/ 25 сентября 2019

У условного типа нет оснований для работы с кортежем, ваш условный тип в основном разрешает вопрос [typeof Position, typeof Status] extends Attribute<infer T>, который явно не подходит, поэтому вы никогда не получите никогда.

Вы можете передать в объединениев тип (AttributeTypes<typeof Position | typeof Status>), и тогда вы получите Position[] | Status[], что не совсем то, что вы хотите ( Play )

Вы также можете использовать массив в вашем условном типе (Attributes extends Array<Attribute<infer T>> ? T[] : never), но это не сохранит структуру кортежа на входе ( Play )

Лучший способ получить желаемый результат - использовать сопоставленный тип.Отображенные типы сохраняют кортеж, позволяя вам сопоставить каждый тип элемента кортежа с новым типом элемента в результирующем кортеже:

type Attribute<Type> = { id: string, type?: Type };

type Position = { x: number, y: number };
let Position: Attribute<Position> = { id: "position" };

type Status = "active" | "inactive";
let Status: Attribute<Status> = { id: "status" };

type AttributeTypes<Attributes extends Attribute<any>[]> = {
  [P in keyof Attributes]: Attributes[P] extends Attribute<infer T> ? T : never;
}

type Result = AttributeTypes<[typeof Position, typeof Status]> // is [Position, Status]

Play

...