Enums are a TypeScript-only feature, by which I mean, there is no formal definition of an enum in JavaScript. At compile time, the enum itself is erased, and all that is left (for non-const) enums is a simple object; for example...
var MyNumber;
(function (MyNumber) {
MyNumber["ONE"] = "ONE";
MyNumber["TWO"] = "TWO";
MyNumber["THREE"] = "THREE";
MyNumber["FOUR"] = "FOUR";
MyNumber["FIVE"] = "FIVE";
})(MyNumber || (MyNumber = {}));
You'll notice there that the object itself, of course has a type (MyNumber
), but the members of MyNumber
are not of type MyNumber
, and this is why you cannot identify the type of an enum from one of its members.
Note: Enums in TypeScript (and even C#) suck! They are just named values, unlike in Java where they are fully qualified objects with enum semantics.
What you could do is implement an enum class, rather than using TypeScript's built-in enum. I've seen this practice used quite a lot in the C# community.
Here is an abstract class for implementing enums...
abstract class Enum {
protected constructor(public readonly value: number, public readonly name: string) {
}
public toString(): string {
return this.name;
}
public valueOf(): number {
return this.value;
}
public static getAll<T extends Enum>(): T[] {
const enumeration: {[key:string]:any} = this;
return Object
.keys(enumeration)
.filter(name => enumeration[name] instanceof this)
.map(name => enumeration[name]);
}
}
And here is how you would implement it...
class MyNumber extends Enum {
public static readonly ONE: MyNumber = new MyNumber(1, "ONE");
public static readonly TWO: MyNumber = new MyNumber(2, "TWO");
public static readonly THREE: MyNumber = new MyNumber(3, "THREE");
public static readonly FOUR: MyNumber = new MyNumber(4, "FOUR");
public static readonly FIVE: MyNumber = new MyNumber(5, "FIVE");
// Make sure this is private so consumers can't add to or edit your enum!
private constructor(public readonly value: number, public readonly name: string) {
super(value, name);
}
}
And here's a test...
const value = MyNumber.ONE;
const proto: typeof Enum = value.constructor as typeof Enum;
console.log(proto.name);
console.log(proto.getAll());
And the output...
"MyNumber"
[MyNumber: {
"value": 1,
"name": "ONE"
}, MyNumber: {
"value": 2,
"name": "TWO"
}, MyNumber: {
"value": 3,
"name": "THREE"
}, MyNumber: {
"value": 4,
"name": "FOUR"
}, MyNumber: {
"value": 5,
"name": "FIVE"
}]
And the playground: Playground
Note: There are some added benefits to this; for example, currently in TypeScript, you can't do T extends enum
, but with this approach, you can do T extends Enum
.