Difference between string enums and string literal types in TS
Solution 1:
The key thing to understand is that the values of string enums are opaque.
The intended use case for a string enum is that you don't want other code to know or care what the literal string backing MyKeyType.FOO
is. This means that you won't be able to, say, pass the literal string "bar"
to a function accepting a MyKeyType
-- you'll have to write MyKeyType.BAR
instead.
Solution 2:
Well, there is a difference between string enums and literal types in the transpiled code.
Compare the Typescript Code
// with a String Literal Type
type MyKeyType1 = 'foo' | 'bar' | 'baz';
// or with a String Enum
enum MyKeyType2 {
FOO = 'foo',
BAR = 'bar',
BAZ = 'baz'
}
With the transpiled JavaScript Code
// or with a String Enum
var MyKeyType2;
(function (MyKeyType2) {
MyKeyType2["FOO"] = "foo";
MyKeyType2["BAR"] = "bar";
MyKeyType2["BAZ"] = "baz";
})(MyKeyType2 || (MyKeyType2 = {}));
What you can see is, there is no generated code for the string literal. Because Typescripts Transpiler is only using for type safety while transpiling. At runtime string literals are "generated to dumb" strings. No references between the definition of the literal and the usages.
So there is a third alternative called const enum
Look at this
// with a String Literal Type
type MyKeyType1 = 'foo' | 'bar' | 'baz';
// or with a String Enum
enum MyKeyType2 {
FOO = 'foo',
BAR = 'bar',
BAZ = 'baz'
}
// or with a Const String Enum
const enum MyKeyType3 {
FOO = 'foo',
BAR = 'bar',
BAZ = 'baz'
}
var a : MyKeyType1 = "bar"
var b: MyKeyType2 = MyKeyType2.BAR
var c: MyKeyType3 = MyKeyType3.BAR
will be transpiled to
// or with a String Enum
var MyKeyType2;
(function (MyKeyType2) {
MyKeyType2["FOO"] = "foo";
MyKeyType2["BAR"] = "bar";
MyKeyType2["BAZ"] = "baz";
})(MyKeyType2 || (MyKeyType2 = {}));
var a = "bar";
var b = MyKeyType2.BAR;
var c = "bar" /* BAR */;
For further playing you can check this link
I prefer the const enum case, because of the convenient way of typing Enum.Value. Typescript will do the rest for me to get the highest performance when transpiling.
Solution 3:
One benefit for an enum at development time is that you will see the list of options easily via intellisense:
Similarly, you could change an enum value easily using refactoring tools, instead of changing a string everywhere.
Edit: In VS 2017 and TypeScript >=3.2.4, intellisense works with string literal types: