Use computed values on enums

Viewed 1412

I have the following situation:

enum T {
    A = "a"
};

enum U {
    [T.A] = "u"
}

I getting this error:

Computed property names are not allowed in enums.

Is there a way to workaround it? Or maybe using a similar resource that would allow me to have similar behavior?

1 Answers

One option, while not necessarily ideal, is to use the explicit values from the T enum then have some compile time assertion using a dummy type definition:

enum T {
    A = "a"
};

enum U {
    // T.A
    a = "u"
}
/** this raises a compile error if not all values of enum T are valid keys of the enum U */
type _ensure_keyof_U_equals_T = typeof U[T];

This is to ensure that a value of type T can be used as a dynamic key into the U object that is created at runtime. Note that one of the advantages of enums is that making them const which is not an option with this kind of architecture.

An alternative is to make U a object definition instead of a enum like this:

type U = (typeof U)[keyof typeof U]
const U = {
    [T.A]: "u"
} as const

This doesn't assert that every possible element of T is a valid key (although the assertion used above would still work) but does create an object / type combination that is nearly indistinguishable from the enum case, the only difference is that checks for string literals are a little less strict:

enum A {
    a = "b"
}
type B = (typeof B)[keyof typeof B];
const B = {
    element: "b"
} as const

function should_only_accept_enum_A(item: A){}
function should_only_accept_enum_B(item: B){}

should_only_accept_enum_A("b") // fails
should_only_accept_enum_B("b") // succeeds
Related