0

EDIT: I stumbled upon this problem, because I made a wrong assumption. It is thus not a good question but the accepted answer explains my mistake well. I thus consider it still worth being archived here.


I have:

enum TimePeriod {
    Custom = 0,
    LastWeek = 1,
}

I also have a drop down HTML element with values 0 or 1, depending on what the user chose (Custom or LastWeek). I want a simple if (val === TimePeriod.Custom), but I cannot figure out what val should be.

I understand that:

const val = $("#TimePeriod").val() as number;

will not work (ie. above if always false), because val is a number and not a TimePeriod

EDIT: This is the wrong assumption!

const val = $("#TimePeriod").val() as TimePeriod;

will not work, either, because the as TimePeriod-part is lost then it is converted to JS. It is thus exactly the same as the first try.

Also tried:

const val = TimePeriod[$("#TimePeriod").val() as number];

But then val is a string, e.g. "Custom"

What val must actually be is an instance of a enum value, e.g. TimePerios.Custom. But how do I obtain it dynamically having only number 0?

I read Cast int to enum strings in Typescript and even How do I convert a string to enum in TypeScript? but it does not help.

Jack Miller
  • 4,734
  • 2
  • 32
  • 46
  • `as number` also doesn’t do anything at runtime. At runtime, `val` Is probably a string and your enum is a number. To compare them you should actually convert `val` to a number, via some method like prefixing `+` or `Number.valueOf()` or something – jcalz Aug 26 '19 at 10:11
  • 1
    "val is probably a string and your enum is a number" --> Yes, that was it! If you write an answer I can give you credits for it. – Jack Miller Aug 26 '19 at 11:19

1 Answers1

1

The issue is that type assertions (value as Type) have no runtime effect at all; they are just a way of telling the compiler the type of a value when the compiler is unable to infer or verify that for itself. If you use a type assertion you need to be careful that you are not lying to the compiler, and any problems you face at at runtime due to an erroneous assertion are your responsibility to deal with.

Without a type assertion, the following line:

const val = $("#TimePeriod").val(); 

yields a val of the this type:

// const val: string | number | string[] | undefined

So, when you say

const val = $("#TimePeriod").val() as number;

you are claiming that you know val will be a number at runtime, even though all the compiler knows is that it is either a number or a string, or an array of string, or maybe even undefined. Do you know that val will be a number? And if so, how?

My expectation is that .val() generally produces a string, and that it would pretty much never be a number (I guess it [can maybe happen]?(How can val() return Number?)). One way to be sure that you end up with a number is to explicitly convert it to one at runtime:

const val = Number($("#TimePeriod").val()); // number

At that point you can directly compare with TimePeriod members. At runtime, values like TimePeriod.Custom are just numbers, as per the documentation of numeric enums:

console.log(TimePeriod.Custom); // 0
console.log(typeof TimePeriod.Custom); // number

So you can do something like:

switch (val) {
  case TimePeriod.Custom: {
    console.log("custom!")
  }
  case TimePeriod.LastWeek: {
    console.log("last week!")
  }
  default: {
    console.log("who knows?")
  }
}

which should work.


Okay, hope that helps. Good luck!

Link to code

jcalz
  • 125,133
  • 11
  • 145
  • 170