|
| 1 | +import type { Prettify } from "./common"; |
| 2 | +import type { Writeable } from "./writeable"; |
| 3 | + |
| 4 | +type AllowOnlyFirst<TFirstType, TSecondType, TExclusionValue = never> = Prettify< |
| 5 | + // eslint-disable-next-line perfectionist/sort-intersection-types -- I want TFirstType to be first |
| 6 | + TFirstType & Partial<Record<keyof Omit<TSecondType, keyof TFirstType>, TExclusionValue>> |
| 7 | +>; |
| 8 | + |
| 9 | +type AllowOnlyFirstRequired<TFirstType, TSecondType, TExclusionValue = never> = Prettify< |
| 10 | + // eslint-disable-next-line perfectionist/sort-intersection-types -- I want TFirstType to be first |
| 11 | + TFirstType & Record<keyof Omit<TSecondType, keyof TFirstType>, TExclusionValue> |
| 12 | +>; |
| 13 | + |
| 14 | +type MergeTypes< |
| 15 | + TArrayOfTypes extends unknown[], |
| 16 | + TAccumulator = NonNullable<unknown>, |
| 17 | +> = TArrayOfTypes extends [infer TFirstType, ...infer TRest] |
| 18 | + ? MergeTypes<TRest, TAccumulator & TFirstType> |
| 19 | + : TAccumulator; |
| 20 | + |
| 21 | +/** |
| 22 | + * Type utility that extracts discriminated properties from a union of types. |
| 23 | + * Takes an array of types and returns a union of types where each type has unique properties. |
| 24 | + * |
| 25 | + * @template TArrayOfTypes Array of types to process |
| 26 | + * @template TExclusionValue Value to exclude from the resulting union |
| 27 | + * @template TAccumulator Accumulator for the resulting union |
| 28 | + * @template TMergedProperties Merged properties from all types |
| 29 | + */ |
| 30 | + |
| 31 | +export type UnionDiscriminator< |
| 32 | + TArrayOfTypes extends unknown[], |
| 33 | + TExclusionValue = never, |
| 34 | + TAccumulator = never, |
| 35 | + TMergedProperties = MergeTypes<TArrayOfTypes>, |
| 36 | +> = TArrayOfTypes extends [infer TFirstType, ...infer TRest] |
| 37 | + ? UnionDiscriminator< |
| 38 | + TRest, |
| 39 | + TExclusionValue, |
| 40 | + // eslint-disable-next-line perfectionist/sort-union-types -- Let TAccumulator be first |
| 41 | + TAccumulator | AllowOnlyFirst<TFirstType, TMergedProperties, TExclusionValue>, |
| 42 | + TMergedProperties |
| 43 | + > |
| 44 | + : TAccumulator; |
| 45 | + |
| 46 | +/** |
| 47 | + * Type utility that extracts discriminated properties from a union of types. |
| 48 | + * Takes an array of types and returns a union of types where each type has unique properties. |
| 49 | + * |
| 50 | + * @template TArrayOfTypes - Array of types to process |
| 51 | + * @template TExclusionValue - Value to exclude from the resulting union |
| 52 | + * @template TAccumulator - Accumulator for the resulting union |
| 53 | + * @template TMergedProperties - Merged properties from all types |
| 54 | + */ |
| 55 | +export type UnionDiscriminatorRequired< |
| 56 | + TArrayOfTypes extends unknown[], |
| 57 | + TExclusionValue = never, |
| 58 | + TAccumulator = never, |
| 59 | + TMergedProperties = MergeTypes<TArrayOfTypes>, |
| 60 | +> = TArrayOfTypes extends [infer TFirstType, ...infer TRest] |
| 61 | + ? UnionDiscriminatorRequired< |
| 62 | + TRest, |
| 63 | + TExclusionValue, |
| 64 | + // eslint-disable-next-line perfectionist/sort-union-types -- Let TAccumulator be first |
| 65 | + TAccumulator | AllowOnlyFirstRequired<TFirstType, TMergedProperties, TExclusionValue>, |
| 66 | + TMergedProperties |
| 67 | + > |
| 68 | + : TAccumulator; |
| 69 | + |
| 70 | +export type ExtractUnion<TObject, TVariant extends "keys" | "values" = "values"> = TObject extends |
| 71 | + | Array<infer TUnion> |
| 72 | + | ReadonlyArray<infer TUnion> |
| 73 | + | Set<infer TUnion> |
| 74 | + ? TUnion |
| 75 | + : TObject extends Record<infer TKeys, infer TValues> |
| 76 | + ? TVariant extends "keys" |
| 77 | + ? TKeys |
| 78 | + : Prettify<Writeable<TValues, "deep">> |
| 79 | + : never; |
0 commit comments