What is the difference between enum and object in typescript
JavascriptTypescriptObjectEnumsJavascript Problem Overview
I am trying to access values of a map via enum and also make a translation ready app for all the strings in it. Both concerns overlap and I have to decide between using enums or just object in JSON format.
So what exactly is the difference and useage between an enum and an object?
For example:
- I can use enums to access arrays as well as inserting labels and other stuff like
const enum FieldNames { FirstField: "Field One", SecondField: "Field Two" };
someFieldArray[FieldNames.FirstField].label = FieldNames.FirstField; someFieldArray[FieldNames.SecondField].label = FieldNames.SecondField;
- Or I can achieve the same behaviour via object
const FieldNames = {
FirstField: "Field One",
SecondField: "Field Two"
};
someFieldArray[FieldNames.FirstField].label = FieldNames.FirstField;
someFieldArray[FieldNames.SecondField].label = FieldNames.SecondField;
I really do not get the benefit choosing enums over simple objects. In my opinion an object has much more benefits without any downsides.
Javascript Solutions
Solution 1 - Javascript
Enum
An enum may give you additional benefits, if you want the features:
const enum FieldNamesEnum {
FirstField = "Field One",
SecondField = "Field Two"
};
let x: FieldNamesEnum;
x = FieldNamesEnum.FirstField;
x = FieldNamesEnum.SecondField;
// Error - not assignable to FieldNames
x = 'str';
// Cannot assign
FieldNamesEnum.FirstField = 'str';
Importantly, you can't assign to the enum members and types are checked to the enum members, rather than string.
Additionally, because you have used a const enum
in your example, the enum won't exist at runtime and all the references will be substituted for the literal values (if you used a plain enum
the enum would exist at runtime).
Object
Compare this to the object example:
const FieldNames = {
FirstField: "Field One",
SecondField: "Field Two"
};
let y: string;
y = FieldNames.FirstField;
y = FieldNames.SecondField;
// Oops it works
y = 'str';
// Oops it works
FieldNames.FirstField = 'str';
Union
If you don't need the full enum, but want to limit the values, you can use a union of literal values:
type FieldNames = "Field One" | "Field Two";
let x: FieldNames;
x = "Field One";
x = "Field Two";
// Error - not allowed
x = "Field Three";
Solution 2 - Javascript
I don't aggre with @Fenton. Objects are the type safe.
const FieldNames = {
FirstField: 'Field One',
SecondField: 'Field Two',
} as const;
type ValueOf<T> = T[keyof T];
let y: ValueOf<typeof FieldNames>;
y = FieldNames.FirstField;
y = FieldNames.SecondField;
// TS2322: Type '"str"' is not assignable to type '"Field One" | "Field Two"'.
y = 'str';
// TS2540: Cannot assign to 'FirstField' because it is a read-only property
FieldNames.FirstField = 'str';
Solution 3 - Javascript
function (foo: FieldNames) { }
If FieldNames
is an object, this means this function expects an instance which has the properties FirstField
and SecondField
. If FieldNames
is an enum (in which case it should be singular, not plural), this means the function expects one of the values of FieldNames
, namely "Field One"
or "Field Two"
.
Very different usage.
Solution 4 - Javascript
In the Typescript language handbook, you have a dedicated section talking about that: Objects vs Enums.
Personally, when I need a type with a set of options, I prefer using Typescript enum, because it is easier to use. With the enum definition, you have the type and also the way to access the options. To implement the same aproach with an object, you need to define the object as const
and also define an extra type based on it.
Solution 5 - Javascript
this should be main reason.. you can use enum as a type so one of following options, but you cant define cosnt object as a type, it will have all options in one obj :)
you can also do this
type FieldNames = "Field One" | "Field Two";
but if list is long, enum is much better, in ES6 enum is pure useless just use obejct but in typescript its a type and its a main benefit in my opition