Remove redundant intersections when flattening a complex record

31 Views Asked by At

I have a complex Flattened type that gives me a result that is right for me. However the resulting type has a lot of duplicate intersections when, in the input record:

  1. A key is isolated (in the example the key d)
  2. The corresponding value is a union
type Primitive = number | string | boolean | Date;

export type UnionToIntersection<U> =
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  (U extends any ? (k: U) => void : never) extends (k: infer I) => void
    ? I
    : never;

export type Flattened<T, Sep extends string> = T extends
  | Primitive
  | unknown[]
  | Record<string, Primitive | unknown[]>
  ? T
  : T extends Record<string, unknown>
  ? UnionToIntersection<
      {
        [K in keyof T & string]: Flattened<T[K], Sep> extends infer Flat
          ? Flat extends Primitive | unknown[]
            ? { [P in K]: T[P] }
            : Flat extends Record<string, unknown>
            ? {
                [KFlat in keyof Flat &
                  string as `${K}${Sep}${KFlat}`]: Flat[KFlat];
              }
            : Flat extends unknown
            ? { [KFlat in K]: Flat }
            : never
          : never;
      }[keyof T & string]
    >
  : T extends unknown
  ? T
  : never;


type ComplexA = "complexA1" | "complexA2";
type ComplexB = "complexB1" | "complexB2" | "complexB3";


/**
 * Expected type: 
 * {
 *     a_b: ComplexA;
 * } & {
 *     c_d: ComplexB;
 * } & {
 *     d: ComplexB;
 * }
 *
 *
 * Actual type: 
 * {
 *     a_b: ComplexA;
 * } & {
 *     c_d: ComplexB;
 * } & {
 *     d: ComplexB;
 * } & {
 *     d: ComplexB;
 * } & {
 *     d: ComplexB;
 * }
 */
Flattened<
{
  a: { b: ComplexA };
  c: { d: ComplexB };
  d: ComplexB;
}, '_'
>

Here's a link to a playground that also contains an implementation for a flatten function.

0

There are 0 best solutions below