Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript: add more data to enum

In TypeScript, is it possible to add more stuff (properties, methods, etc.) to enum constants, like in Java?

Java example demonstrating adding of fields, methods and constructor:

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7);

    private final double mass;   // in kilograms
    private final double radius; // in meters

    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    private double mass() { return mass; }
    private double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
    // ...
}
like image 444
KarolDepka Avatar asked Apr 12 '17 17:04

KarolDepka


2 Answers

Not using an enum, but you can get the same exact thing using a class and a few static members:

class Planet {
    public static MERCURY = new Planet(3.303e+23, 2.4397e6);
    public static VENUS = new Planet(4.869e+24, 6.0518e6);
    public static EARTH = new Planet(5.976e+24, 6.37814e6);
    public static MARS = new Planet(6.421e+23, 3.3972e6);
    public static JUPITER = new Planet(1.9e+27, 7.1492e7);
    public static SATURN = new Planet(5.688e+26, 6.0268e7);
    public static URANUS = new Planet(8.686e+25, 2.5559e7);
    public static NEPTUNE = new Planet(1.024e+26, 2.4746e7);

    private mass: number;
    private radius: number;

    private constructor(mass: number, radius: number) {
        this.mass = mass;
        this.radius = radius;
    }

    public static G = 6.67300E-11;

    public surfaceGravity(): number {
        return Planet.G * this.mass / (this.radius * this.radius);
    }

    public surfaceWeight(otherMass: number) {
        return otherMass * this.surfaceGravity();
    }
}

console.log(Planet.MERCURY.surfaceGravity());

(code in playground)

In java for each item in the enum a static instance is created, which means that this indeed does the same thing, it's just that java has a nicer syntax for defining enums.


Edit

Here's a version with the equivalent Planet.values() which java will generate:

class Planet {
    public static MERCURY = new Planet(3.303e+23, 2.4397e6);
    public static VENUS = new Planet(4.869e+24, 6.0518e6);
    ...

    private static VALUES: Planet[] = [];

    private mass: number;
    private radius: number;

    private constructor(mass: number, radius: number) {
        this.mass = mass;
        this.radius = radius;

        Planet.VALUES.push(this);
    }

    public static values() {
        return Planet.VALUES;
    }

    ...
}

2nd edit

Here's a way to implement the valueOf:

   public static valueOf(name: string): Planet | null {
        const names = Object.keys(this);
        for (let i = 0; i < names.length; i++) {
            if (this[names[i]] instanceof Planet && name.toLowerCase() === names[i].toLowerCase()) {
                return this[names[i]];
            }
        }

        return null;
    }
like image 54
Nitzan Tomer Avatar answered Oct 15 '22 19:10

Nitzan Tomer


Unfortunately it's not possible. You can just assign property names

See this reference for the TypeScript spec https://github.com/microsoft/TypeScript/blob/30cb20434a6b117e007a4959b2a7c16489f86069/doc/spec-ARCHIVED.md#a7-enums

like image 32
Diullei Avatar answered Oct 15 '22 19:10

Diullei