Ran Lottem
Ran Lottem

Reputation: 486

How to map between enums based on identical key names?

I have two enums with identical key names, and I want to be able to use a value from one enum to get the value from the second enum.

An example would be translating server errors to client errors in an application:

enum serverErrors {
  first = "server error 1",
  second = "server error 2",
  third = "server error 3"
}

enum clientErrors {
  first = "client error 1",
  second = "client error 2",
  third = "client error 3"
}

currently we're using functions like this:

function translate(s: string) {
    switch (s) {
        case serverErrors.first:
            return clientErrors.first;
            /// ...
    }
}

I'd like to be able to do something like the above, without manually specifying what each key should translate to - it should happen based on the name of the key.

I've tried this:

type translator = {
  // Error: Type 'P' cannot be used to index type 'clientErrors'.
  [P in keyof typeof serverErrors]: clientErrors[P];
};

though I'm not sure how to get a string value from the above, even if it did work.

I'd like for this code to work:

const serverError = serverErrors.first;
const clientError = enumTranslator(serverError); // === clientError.first

Upvotes: 0

Views: 155

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249706

Since the keys are the same in both enums, you can just index using the same key. Enums are objects at runtime so you can search one enum to find the values and index into the other enum:

enum serverErrors {
    first = "server error 1",
    second = "server error 2",
    third = "server error 3"
}

enum clientErrors {
    first = "client error 1",
    second = "client error 2",
    third = "client error 3"
}

function translate<
    TSource extends Record<keyof TSource, string>,
    TTarget extends Record<keyof TSource, string>>(source: TSource, target: TTarget, s: string) {

    for (const key in source) {
        if (source[key] === s) {
            return target[key];
        }
    }
    throw new Error("Member not found");
}

let a = translate(serverErrors, clientErrors, serverErrors.first);
console.log(a);

Upvotes: 2

Related Questions