Typescript: проверить, является ли тип объединением
Можно ли проверить, является ли данный тип объединением?
type IsUnion<T> = ???
Зачем мне это нужно: в моем коде у меня есть единственный случай, когда некоторый полученный тип может быть объединением. Я справляюсь с дистрибутивным условным типом. Тем не менее, для того, кто смотрит на этот код, может быть не очевидно, почему DCT используется в первую очередь. Итак, я хочу, чтобы это было явно так: IsUnion<T> extends true? T extends Foo...
IsUnion<T> extends true? T extends Foo...
Я сделал несколько попыток с UnionToIntersection
, но UnionToIntersection
. Я также придумал это:
type IsUnion<T, U extends T = T> =
T extends any ?
(U extends T ? false : true)
: never
Это дает false
для не профсоюзов, но по какой-то причине это дает boolean
для союзов... И я понятия не имею, почему. Я также пытался infer
U из T, но безуспешно.
PS Мой вариант использования может показаться кому-то не идеальным/правильным/хорошим, но в любом случае возник вопрос в названии, и я задаюсь вопросом, возможно ли это (я чувствую, что это так, но мне самому трудно это понять).
Ответы
Ответ 1
Так что, похоже, я сам придумал ответ!
Вот тип (спасибо Тициану Черниковой-Драгомиру за упрощение!):
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true
type Foo = IsUnion<'abc' | 'def'> // true
type Bar = IsUnion<'abc'> // false
И снова пригодился UnionToIntersection из jcalz!
Принцип основан на том, что объединение A | B
A | B
не расширяет пересечение A & B
= (U extends any? (k: U) => void: never) extends ((k: infer I) => void)? I: never
type IsUnion= [T] extends [UnionToIntersection]? false: true
type Foo = IsUnion<'sdf' | 'zcx'>
type Bar = IsUnion<'sdf'> rel="nofollow noreferrer">Детская площадка
UPD. Я был достаточно глуп, чтобы не развивать свой тип из вопроса в этот, который также отлично работает:
type IsUnion<T, U extends T = T> =
(T extends any ?
(U extends T ? false : true)
: never) extends false ? false : true
Он распределяет объединение T
на составляющие, а также T
а затем проверяет, расширяет ли U
который является объединением, составляющую T
Если да, то это не объединение (но я до сих пор не знаю, почему это не работает без добавления extends false? false: true
, т.е. почему предыдущая часть возвращает boolean
для объединений).