In fact, the name of the enum is, itself, an alias for the union of its values' types. The following code demonstrates:
enum WaterType {
Lake = 0,
Ocean = 1,
River = 2,
Creek = 3,
};
let xxx: 0|1|2|3 = 2;
let yyy: WaterType = xxx; // OK
let zzz: 0|1|2|3 = yyy; // OK
Enums are just a little confusing because the enum's name refers to the type (like 0|1|2|3
) in some contexts, but in other contexts it refers to an object by the same name. The WaterType
object is similar to this object:
const WaterTypeObject = {
Lake : 0 as 0,
Ocean : 1 as 1,
River : 2 as 2,
Creek : 3 as 3,
};
And typeof WaterType
is virtually the same as typeof WaterTypeObject
:
let aaa: typeof WaterType = WaterType;
let bbb: typeof WaterTypeObject = aaa; // OK
let ccc: typeof WaterType = bbb; // OK
In contexts where a type is expected, WaterType
means 0|1|2|3
, but you can write typeof WaterType
instead to get the type of the enum object:
// VS code reports: type WaterTypeString = "Lake" | "River" | "Ocean" | "Creek"
type WaterTypeString = keyof typeof WaterType;
// VS code reports: type WaterTypeNumbers = WaterType
// which really means type WaterTypeNumbers = 0|1|2|3
type WaterTypeNumbers = (typeof WaterType)[WaterTypeString];
Just be sure not to write "keyof Enum", e.g. keyof WaterType
is the same as keyof number
, which is definitely not what you want.
Fun fact: keyof typeof WaterType
is a lie. the keys of WaterType
are actually "Lake"|"River"|"Ocean"|"Creek"|0|1|2|3
(e.g. WaterType["Creek"]==3
and WaterType[3]=="Creek"
.)