19

I'd like to ask if it's possible to add an enum similar to:

STATES = {
    WIP: "Work in progress",
    ONLINE: "Online",
    ONLINE_MODIFIED: "Online, modified",
    HIDDEN: "Hidden"
}

inside a Class, and be able to use it in some other file with something similar to: object.updateState(Class.STATES.HIDDEN) without having to construct a new object like boxObject.updateState(new Box().STATES.HIDDEN)

Thank you.

Maxime M.
  • 357
  • 1
  • 4
  • 17
  • 5
    That is possible, but why would you want to do that? I would use `export const STATES = { … };` instead. And then you can import it where you need it in other files. – nils Mar 24 '17 at 13:15

4 Answers4

29

You can achieve static data properties in multiple ways:

Use assignment:

const STATES = {
  WIP: "Work in progress",
  ONLINE: "Online",
  ONLINE_MODIFIED: "Online, modified",
  HIDDEN: "Hidden"
};

class Box {};

Box.STATES = STATES;
console.log(Box.STATES.WIP); // Work in progress is the output

Use Object.defineProperty:

When you use Object.defineProperty you could make it read-only

const STATES = {
  WIP: "Work in progress",
  ONLINE: "Online",
  ONLINE_MODIFIED: "Online, modified",
  HIDDEN: "Hidden"
};

class Box {};

Object.defineProperty(Box, 'STATES', {
  value: STATES,
  writable: false, // makes the property read-only
});

console.log(Box.STATES.WIP); // Work in progress is the output

Use static getter:

You can use ES6 static getter syntax to add the property in the class definition. You can make it read-only too defining just the getter.

const STATES = {
  WIP: "Work in progress",
  ONLINE: "Online",
  ONLINE_MODIFIED: "Online, modified",
  HIDDEN: "Hidden"
};

class Box {
  static get STATES() {
    return STATES;
  }
}

console.log(Box.STATES.WIP); // Work in progress is the output

All that being said, I agree with n00dl3. If you are using ES6 modules, using a named export seems more appropiate:

export const BOX_STATES = {
  WIP: "Work in progress",
  ONLINE: "Online",
  ONLINE_MODIFIED: "Online, modified",
  HIDDEN: "Hidden"
};

export default class Box {};

So you can import it like this:

import { BOX_STATES } from './path-to-box';

console.log(BOX_STATES.WIP); // Work in progress is the output
Community
  • 1
  • 1
pablogq
  • 446
  • 4
  • 8
  • The const may be misleading there though. One can still do BOX_STATES.WIP = 'Wewy impowtant pewson' without an error, and change the value of the "constant". – Predrag Stojadinović Feb 12 '18 at 10:11
  • The static getter in the third example above must be accessed by the class or class constructor, not a class instance. To get a class from an instance, use the constructor: `Box.constructor.STATES.WIP`. [Mozilla doc on static](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static#Examples) provides further examples. – Noel Jan 09 '19 at 21:00
  • Another simple option can be using `freeze()` in this way: `class Box { static STATES = Object.freeze({ WIP: "Work in progress", ONLINE: "Online", ONLINE_MODIFIED: "Online, modified", HIDDEN: "Hidden" }) }` – ManSamVampire May 08 '22 at 17:58
16

like this :

export class Foo{}
Foo.SomeStaticEnum={BAR:"bar"};

but exporting a const seems more appropriate...

export const FOO={BAR:"bar"};
n00dl3
  • 21,213
  • 7
  • 66
  • 76
  • 1
    Sorry for being late. You just about solved the problem mere minutes after the question was posted. So you get the checkmark despite the next person's more detailed answer. – Maxime M. Mar 27 '17 at 17:37
  • Why exporting separately is better? – h3dkandi Aug 05 '20 at 07:54
  • @h3dkandi Because declaring an empty class just to export a static property seems overkill : you declare 2 things while you just use a single one. – n00dl3 Aug 05 '20 at 08:01
  • What if the enum is used in conjunction with the class only? Say I have a class Beer and I have an enum Beer.StandardBeers and you use it lets say like this new Beer(Beer.StandardBeers) or sth. – h3dkandi Aug 05 '20 at 08:04
  • 1
    Well it's a big topic but, it's still better to keep it out of your class because if it is part of your class, it will always get imported wether you use it or not (`import {myClass} from "x/y"`). If you keep it separated (`import {myClass} from "x/y"`,`import {myEnum} from "x/y"`)and you import it separately, if you enable tree-shaking, you can only bundle the class or only the enum, which will make you gain a few bytes in your bundle size. – n00dl3 Aug 05 '20 at 08:09
2

If you don't need pure ES6 and can use Typescript, please prefer it. Typescript has a nice ENUM with export options

Example:

export enum STATES
{
        WIP = "Work in progress",
        ONLINE = "Online",
        ONLINE_MODIFIED = "Online, modified",
        HIDDEN = "Hidden"
}

export class SocialMedia
{
    static state: STATES = STATES.HIDDEN;
}


console.log(SocialMedia.state);
SocialMedia.state = STATES.WIP;
console.log(SocialMedia.state);

Result:

Hidden
Work in progress
Anandaraja_Srinivasan
  • 568
  • 1
  • 10
  • 25
0

Another simple way of doing this without the need of class

const BOX_STATES = {
  WIP: "Work in progress",
  ONLINE: "Online",
  ONLINE_MODIFIED: "Online, modified",
  HIDDEN: "Hidden"
};

module.exports = BOX_STATES;

console.log(BOX_STATES.WIP);

Make sure you import or require your file, as shown above.

Mohamed Salem Lamiri
  • 5,767
  • 6
  • 34
  • 47