// 你的答案
type IsUnion<T, U = T> = [T] extends [never] ? false : T extends U ? [U] extends [T] ? false: true : false;
Solution by HelloGGG #33423
// your answers
type IsUnion<T, K = T> = [T] extends [never]
? false
: K extends K
? [T] extends [K]
? false
: true
: never
Solution by pea-sys #32610
type IsUnion<T, C = T> =
(T extends unknown
? C extends T
? true
: false
: never) extends true ? false : true
분배법칙이 일어났을 때의 T와 정적으로 C가 가지고 있는 타입의 관계를 비교하여 Union인지 아닌지를 체크할 수 있다.
Solution by dev-hobin #32422
type IsUnion<T, K = T> = [T] extends [never]
? false
: K extends K
? [T] extends [K]
? false
: true
: never
Solution by yoonnokdoo #32395
type IsUnion<T, S = T> = [T] extends [never]
? false
: S extends S
? Equal<T, S> extends true
? false
: true
: never
type IsUnion<T, S = T> = [T] extends [never]
? false
: S extends S
? NotEqual<T, S>
: never
Solution by Heonys #32100
// your answers
// 使用 296 的 Permutation,得出笛卡尔乘积组合解决
type Permutation<T, U extends T = T> = [T] extends [never]
? []
: U extends U
? [U, ...Permutation<Exclude<T, U>>]
: never;
type IsUnion<T> = Permutation<T>['length'] extends (0 | 1) ? false : true;
Solution by wenxiangdong #31760
type IsUnion<T, U = T> = [T] extends [never]
? false
: T extends infer V
? [Exclude<U, V>] extends [never] ? false : true
: never
Solution by kai-phan #31667
type IsUnion<T> = { [K in T as T extends K ? 'false' : 'true']: true } extends { true: true } ? true : false;
Basic idea: match every member in a union against everything and map this to a mapped type with "true"/"false" keys, then try to match for "true" key.
PS: I'm not sure if I used the correct language or if I properly understood how everything works.
Solution by tany1 #31604
type IsUnion<T, B = T> = [T] extends [never]
? false
: T extends B
? [B] extends [T]
? false
: true
: never;
Solution by vipulpathak113 #31538
With NotEqual
.
// your answers
type IsUnion<T> = NotEqual<[T] & T, (T extends T ? [T] : never) & T>;
Solution by sugoroku-y #31477
Referenced Equal
.
// your answers
type IsUnion<T> = (
T extends T ? <S>() => S extends T ? 1 : 2 : never
) extends <S>() => S extends T ? 1 : 2
? false
: true;
@doox911-opensource commented
I think this is the best solution. And great explanation.
But the test:
Expect<Equal<IsUnion<(() => any)|(() => 15)>, true >>,
failed
This test case has also been successful.
Solution by sugoroku-y #31295
type IsUnionImpl<T, C extends T = T> = (T extends T ? C extends T ? true : unknown : never) extends true ? false : true;
type IsUnion<T> = IsUnionImpl<T>;
Solution by MyeonghoonNam #30992
type IsUnion<T, K = T> =
[T] extends [never]
? false
: K extends K
? [Exclude<T, K>] extends [never]
? false
: true
: false;
Solution by vprokashev #30955
// your answers
type UnionToArray<T> = T extends T ? Array<T> : never
type IsUnion<T> = [T] extends [never] ? false : Array<T> extends UnionToArray<T> ? false : true
Solution by yangdonglai #30722
type IsUnion<T, R = T> = [T] extends [never] ? false : (T extends any ? ([Exclude<R, T>] extends [never] ? false : true) : true);
Solution by kai-phan #30391
export type IsUnion<U> = _IsUnionImpl<U, U>;
/** @internal */
type _IsUnionImpl<U, K extends U> = IsNever<U> extends true
? false
: K extends K
? BoolNot<TypeEq<U, K>>
: never;
type IsNever<T> = [T] extends [never] ? true : false;
// https://github.com/microsoft/TypeScript/issues/27024
type TypeEq<A, B> =
(<T>() => T extends A ? 1 : 2) extends
(<T>() => T extends B ? 1 : 2)
? true
: false;
type BoolNot<A extends boolean> =
TypeEq<A, true> extends true
? false
: TypeEq<A, false> extends true
? true
: never;
/**
* @param _relation `"=" | "<=" | "!="`
* @description
* - `expectType<A, B>("=")` passes if `A` is equal to `B`.
* - `expectType<A, B>("<=")` passes if `A` extends `B`.
* - `expectType<A, B>("!=")` passes if `A` is not equal to `B`.
*/
const expectType = <A, B>(
_relation: TypeEq<A, B> extends true
? '<=' | '='
: TypeExtends<A, B> extends true
? '!=' | '<='
: '!<=' | '!='
): void => undefined;
expectType<IsUnion<never>, false>('=');
expectType<IsUnion<string>, false>('=');
expectType<IsUnion<number | string>, true>('=');
expectType<IsUnion<[number | string]>, false>('=');
expectType<
IsUnion<Readonly<{ a: 0 }> | Readonly<{ a: 1; b: 1 }> | Readonly<{ b: 2 }>>,
true
>('=');
expectType<IsUnion<Record<number, number> | Record<string, number>>, true>('=');
expectType<
IsUnion<
| Readonly<{ a: 0 }>
| Readonly<{ a: 1; b: 1 }>
| Readonly<{ b: 2 }>
| Record<string, number>
>,
true
>('=');
WIP
Solution by noshiro-pf #29976
type IsUnionImpl<T, C extends T = T> =
(T extends infer TItem // Iterate over T, here TItem is an item from the original union T. Ingredients 1&2
? C extends TItem // C holds the original union T. Does union T extends an item from it? // Ingredient 3
? true // yes. that could only be true if union T consist of one item
: false // no
: never) extends true ? false : true // have we got true from the above? yes - it's not a union
type IsUnion<T> = IsUnionImpl<T>
Solution by qianzhong516 #29913
type IsUnion<T, U = T> = [T] extends [never] ? false : T extends U ? IsUnion<Exclude<U, T>, T> : true
Solution by Yirujet #29539
// your answers
type IsUnion<T> = HasMoreThanOnePermutation<T>;
type Permutation<T, acc extends any[] = [], ALL = T> = [T] extends [never]
? acc
: T extends T
? Permutation<Exclude<ALL, T | acc[number]>, [...acc, T], ALL>
: acc;
type HasMoreThanOnePermutation<T extends any> = Permutation<T> extends [
infer U,
...infer R
]
? [U] extends [never] // size 0
? false
: R extends never[] // size 1
? false
: true //more than 1 permutation
: false; // should never happen
Solution by lamine-ndouop-deel #29422
type IsUnion<T, U = T> =[T] extends [never] ? false : T extends U ? [U] extends [T] ? false : true : never
Solution by IvanKoigerov #28884
type IsNever<T> = [T] extends [never] ? true : false;
type IsUnion<T, I = T> = IsNever<T> extends true ? false : (T extends I ? [I] extends [T] ? false : true : false)
Solution by hajeonghun #28759
type IsEqual<A, B> = (
type IsUnion<T, U = T> = [T] extends [never] ? false : T extends U ? IsEqual<T, U> extends true ? false : true : never;
Solution by DoubleWoodLin #28643
// your answers
type IsUnion<T, B = T> = [T] extends [never] ? false : T extends B ? [B] extends [T] ? false : true : never;
Solution by ixiaolong2023 #27786
type IsUnion<T, C = T> = [T] extends [never]
? false
: C extends C
? [Exclude<T, C>] extends [never]
? false
: true
: never;
Solution by idebbarh #27600
type IsUnion<T, B = T> = T extends B ? [T] extends [B] ? false : true : never;
Solution by vuongManabie #26846
type IsUnion<T, U = T> = (T extends T ? U extends T ? true : unknown : never) extends true ? false : true
思路:
Solution by smileboyi #26845
type IsUnion<T, B = T> = [T] extends [never]
? false
: T extends B
? [B] extends [T]
? false : true
: false
Solution by avatar0813 #26737
type IsUnion<T, K = T> = [T] extends [never] ? false : T extends K ? ([K] extends [T] ? false : true) : never;
Solution by 8471919 #26701
type IsUnion<T, B = T> = [T] extends [never] ? false : T extends B ? [B] extends [T] ? false : true : false;
Solution by AwesomeYelim #26592
type IsPartitionSameEntire<T, P = T> = T extends P ? P extends T ? false : true : false;
type IsUnion<T> = IsPartitionSameEntire<T> extends true ? false : IsPartitionSameEntire<T> extends false ? false : true;
Solution by kakasoo #26326