I wrote this post under the influence of the article “WHY I DON’T USE
ENUMS IN TYPESCRIPT, AND NEITHER SHOULD YOU” (now deleted). In short,
the author suggested using objects instead of enums in TS.
That is, instead of:
enum Colors {
BLUE = 'blue',
GREEN = 'green',
RED = 'red',
}
function printColor(color: Colors) { console.log(color); }
printColor(Colors.BLUE);
printColor('blue');
it was proposed to use something like:
const Colors = {
BLUE: 'blue',
GREEN: 'green',
RED: 'red',
} as const;
type Colors = typeof Colors[keyof typeof Colors];
function printColor(color: Colors) { console.log(color); }
printColor(Colors.BLUE);
printColor('blue');
The author cited the ability to use literals (blue) instead of
importing the source file with the enum and using its values as an
advantage of this approach.
I have an article “So, What Is the Ultimate Goal of Programming?” in which I examine the sequence of programming goals in a hierarchy similar to Maslow’s pyramid:
The goals
And I dare to claim that the approach with literals instead of enums corresponds to the first level of goals — convenience of writing code, but does not correspond to the highest level of goals I have seen — The Modifying.
Indeed, a string literal is much more convenient for writing code.
invoice.setState('pending');
order.setState('pending');
But a search for the pending state of an order now collides with
similar invoice states. This is the trade-off for avoiding imports and
literals.
In my JS code, I use namespaces taken from Zend1
const TeqFw_Core_Shared_Enum_Sphere = {
BACK: 'BACK',
FRONT: 'FRONT',
SHARED: 'SHARED',
};
Object.freeze(TeqFw_Core_Shared_Enum_Sphere);
export default TeqFw_Core_Shared_Enum_Sphere;
and during the call, I use dependency injection and JSDocs.
export default function ({TeqFw_Core_Shared_Enum_Sphere$: SPHERE}) {
if (one.sphere === SPHERE.FRONT || one.sphere === SPHERE.SHARED) {
// ...
}
}
This lets us find every use of TeqFw_Core_Shared_Enum_Sphere with a
text search. JSDoc also helps the IDE navigate to each enum value.
Yes, unlike TS, such an approach does not prohibit the use of literals directly when calling code:
if (one.sphere === 'FRONT' || one.sphere === 'SHARED') {
// ...
}
However, it is your responsibility as a programmer to use the capabilities of the available tools for good and not for evil.
Yes, I understand that enum is not actually implemented in JS
(although the word itself is reserved), but I believe that you can write
code as if it were there even without it :)