Преобразовать тип объединения в тип пересечения - PullRequest
0 голосов
/ 16 мая 2018

Есть ли способ преобразовать тип объединения в тип пересечения:

type FunctionUnion = () => void | (p: string) => void
type FunctionIntersection = () => void & (p: string) => void

Я хотел бы применить преобразование к FunctionUnion, чтобы получить FunctionIntersection

Ответы [ 2 ]

0 голосов
/ 07 мая 2019

Если вы пытаетесь преобразовать массив в пересечение , предварительное отображение массива приведет к тому, что результирующее объединение массивов будет иметь неправильный порядок .

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

Ниже поддерживаются массивы вплоть до индекса 9, который можно расширить вручную, если вам требуется более длительная рекурсия.

type Idx<T extends any, K extends keyof any, Yes> = T extends Record<K, any>
  ? T[K] & Yes
  : unknown

type ArrayToIntersection<T extends any[]> = Idx<T, '0', Idx<T, '1', Idx<T, '2', Idx<T, '3', Idx<T, '4', Idx<T, '5', Idx<T, '6', Idx<T, '7', Idx<T, '8', Idx<T, '9', unknown>>>>>>>>>>

// Usage: => 1 & 2 & 3 & 4
type Result = ArrayToIntersection<[1, 2, 3, 4]>
0 голосов
/ 16 мая 2018

Вы хотите объединение на пересечении? Распределительные условные типы и могут выводить из условных типов .(Не думайте, что возможно сделать пересечение к союзу, извините) Вот злая магия:

type UnionToIntersection<U> = 
  (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never

Это распределяет союз U и упаковывает его в новый союз, где все составляющиенаходятся в контравариантном положении.Это позволяет выводить тип как пересечение I, как упомянуто в справочнике:

Аналогичным образом, несколько кандидатов на одну и ту же переменную типа в противоположных позициях приводят к выводу типа пересечения.


Давайте посмотрим, работает ли он.

Сначала позвольте мне заключить в скобки ваши FunctionUnion и FunctionIntersection, потому что TypeScript, кажется, связывает объединение / пересечение более тесно, чем функцияreturn:

type FunctionUnion = (() => void) | ((p: string) => void);
type FunctionIntersection = (() => void) & ((p: string) => void);

Тестирование:

type SynthesizedFunctionIntersection = UnionToIntersection<FunctionUnion>
// inspects as 
// type SynthesizedFunctionIntersection = (() => void) & ((p: string) => void)

Хорошо выглядит!

Будьте осторожны, что в целом UnionToIntersection<> раскрывает некоторые детали того, что TypeScript считает действительным объединением,Например, boolean, по-видимому, внутренне представляется как true | false, поэтому

type Weird = UnionToIntersection<string | number | boolean>

становится

type Weird = string & number & true & false

Надежда, которая помогает.Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...