3

I have a function which accepts an argument which has type of a few different enums in typescript. I want to check which enum type does an argument have. Is it even possible to check? Here is an example code:

enum X {
    ONE,
    TWO
}

enum Y {
    THREE,
    FOUR
}

function check(arg1: X | Y) {
    if (arg1 is X) {
        // do something with X
    }
    if (arg1 is Y) {
        // do something with Y
    }
}

3 Answers 3

3

You could use an enum type guard function as in

Generic enum type guard

In this case:

enum X {
    ONE,
    TWO
}

enum Y {
    THREE = 3,
    FOUR
}

const isSomeEnum = <T>(e: T) => (token: any): token is T[keyof T] =>
    (Object as any).values(e).includes(token as T[keyof T]);

function check(arg1: X | Y) {
    if (isSomeEnum(X)(arg1)) {
        console.log('Arg is X')
    }
    if (isSomeEnum(Y)(arg1)) {
        console.log('Arg is Y')
    }
}

check(X.ONE)
check(Y.THREE)
check(X.TWO)
check(Y.FOUR)

To make this work you need to make sure that the enum values do not overlap, which is why you need to include 'THREE = 3' in the definition of Y.

Sign up to request clarification or add additional context in comments.

Comments

1

When you describe a variable using an enum type (e.g., let value: X = X.ONE) that variable expects a value of one of the enum's properties but not the enum itself. The main idea of an enum is to document and reuse a group of values (e.g., enum Colors {BLUE: '#0000ff', YELLOW: '#ffff00'}). So, if you describe a variable using the Colors enum, the variable would accept either Colors.BLUE or Colors.YELLOW which resolve to an actual value of a color (e.g., '#0000ff'); so that variable won't be able to hold the Colors enum itself, just the enum's values.

Enums remain in the compiled code as objects. For example, enums X and Y in your example turn into the following objects:

var X = { '0': 'ONE', '1': 'TWO', ONE: 0, TWO: 1 }
var Y = { '0': 'THREE', '1': 'FOUR', THREE: 0, FOUR: 1 }

In your function, arg1 will contain a value of one of these enums, that is either 0 or 1. So, in your example, you will be able to check whether arg1 belongs to one of these objects (e.g., X[arg1] !== undefined), but you won't be able to guarantee that arg1 belongs to only X or only Y, because both X and Y at some point may contain same keys and or values (e.g., both will have the key 'ONE').

So, we need to make decisions based on value comparisons, like this:

if (arg1 === X.ONE) {
  // do something
}

if (arg2 === Y.THREE) {
  // do something
}

or by checking whether a value belongs to a particular enum object:

if (X[arg1] !== undefined) {
  // do something
}

if (Y[arg1] !== undefined) {
  // do something
}

There is no TS feature that checks whether a value belongs to a particular enum exclusively.

Comments

0

Not possible. Do not forget that

Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript.

Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases. TypeScript provides both numeric and string-based enums.

https://www.typescriptlang.org/docs/handbook/enums.html

In your example: X.ONE = Y.THREE = 0, X.TWO = Y.FOUR = 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.