mannok
mannok

Reputation: 1861

Typescript - Merge two dynamically processed enum into one

/* I have enum A & B at first */
enum A {
  FOO = 'BAR',
  GAR = 'ZAR'
}

enum B {
  FOO = 'BAR'
}


/* Is there any way to retrieve something merged like this? */
enum Merged {
  A_FOO = 'A_BAR',
  A_GAR = 'A_ZAR',
  B_FOO = 'B_BAR'
}

I have 2 enums and I cannot guarantee their keys are mutually exclusive. Also, I want to pre-process their values before merging as well.

May I know if there any way to achieve this?

Upvotes: 1

Views: 1398

Answers (1)

Gerrit0
Gerrit0

Reputation: 9192

Constructing a type for this is possible, but not until TS 4.1, which gives us template literal types.

In TS 4.1 you can define a helper type Prefix, which does the magic:

type Prefix<T extends { [K in keyof T]: string }, P extends string> = {
  [K in keyof T & string as `${P}_${K}`]: `${P}_${T[K]}`
}

Then, it is straightforward to define a Merge function which uses this type to construct a merged enum.

function merged<
  T1 extends { [K in keyof T1]: string }, P1 extends string,
  T2 extends { [K in keyof T2]: string }, P2 extends string,
>(obj1: T1, prefix1: P1, obj2: T2, prefix2: P2): Prefix<T1, P1> & Prefix<T2, P2> {
  const result = {} as any; // Going to have to cast somewhere anyways...

  for (const [k, v] of Object.entries(obj1)) {
    result[`${prefix1}_${k}`] = `${prefix1}_${v}`;
  }

  for (const [k, v] of Object.entries(obj2)) {
    result[`${prefix2}_${k}`] = `${prefix2}_${v}`;
  }

  return result;
}

const Merged = merged(A, 'A', B, 'B')
console.log(Merged) // { A_FOO: "A_BAR", A_GAR: "A_ZAR", B_FOO: "B_BAR" } 

You can try this out on the TypeScript playground, or install typescript@next in your project. TS 4.1 is planned to release on November 17th.

Upvotes: 2

Related Questions