// ============================================================================ // Helpers // ============================================================================ /** * @description Strict version of builtin `Extract`, `U` must be subset of `T`. */ export type StrictExtract = Extract /** * @description Strict version of builtin `Exclude`, `U` must be subset of `T`. */ export type StrictExclude = Exclude // ============================================================================ // Manipulation // ============================================================================ /** * @description Get the shared members of two union types. * * @example * ``` * // Expect: "2" | "3" * UnionIntersection<'1' | '2' | '3', '2' | '3' | '4'>; * * // Expect: () => void * UnionIntersection void), Function>; * ``` */ export type UnionIntersection = UnionA extends UnionB ? UnionA : never /** * @description Get the members that exist in the first union but not in the second. * * @example * ``` * // Expect: "1" * UnionDifference<'1' | '2' | '3', '2' | '3' | '4'>; * * // Expect: string | number * UnionDifference void), Function>; * ``` */ export type UnionDifference = UnionA extends UnionB ? never : UnionA /** * @description Get the complement of a sub-union within a larger union. * * @example * ``` * // Expect: "1" * UnionComplement<'1' | '2' | '3', '2' | '3'>; * ``` */ export type UnionComplement = UnionDifference /** * @description Get the members that belong to exactly one of the two unions. * * @example * ``` * // Expect: "1" | "4" * UnionSymmetricDifference<'1' | '2' | '3', '2' | '3' | '4'>; * ``` */ export type UnionSymmetricDifference = UnionDifference< UnionA | UnionB, UnionA & UnionB > /** * @description Get one stable trailing member from a union. * * @example * ``` * // Expect: "c" * type Result = LastOfUnion<'a' | 'b' | 'c'> * ``` */ export type LastOfUnion = UnionToIntersection void : never> extends ( x: infer L, ) => void ? L : never /** * @description Remove one trailing member from a union. * * @example * ``` * // Expect: "a" | "b" * type Result = UnionPop<'a' | 'b' | 'c'> * ``` */ export type UnionPop = Exclude> // ============================================================================ // Conversion // ============================================================================ /** * @description Convert a union type to an intersection type. * * @example * ``` * // Expect: { name: string } & { age: number } & { visible: boolean } * UnionToIntersection<{ name: string } | { age: number } | { visible: boolean }> * ``` * * @see {@link https://stackoverflow.com/a/50375286/7381355} */ export type UnionToIntersection = ( Union extends unknown ? (_: Union) => void : never ) extends (_: infer Result) => void ? Result : never type InternalUnionToTuple = [U] extends [never] ? T : InternalUnionToTuple>, [LastOfUnion, ...T]> /** * @description Convert a union type to a tuple type. * * @example * ``` * // Expect: ["1", "2", "3"] * type Example = UnionToTuple<'1' | '2' | '3'> * ``` */ export type UnionToTuple = InternalUnionToTuple