TypeScript:向枚举类型添加更多数据

14
在TypeScript中,是否可以像Java一样为枚举常量添加更多的内容(属性、方法等)?
Java示例演示了如何添加字段、方法和构造函数:
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();
    }
    // ...
}
3个回答

16

不使用枚举,但是您可以使用类和一些静态成员来获得完全相同的效果:

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());

( 在游乐场中的代码)

在 Java 中,枚举中的每个项目都会创建一个静态实例,这意味着它确实做了相同的事情,只是 Java 为定义枚举提供了更好的语法。

编辑

这是一个包含等效的 Planet.values() 的版本,它将由 Java 生成:

class Planet {
    private static VALUES: Planet[] = [];

    public static MERCURY = new Planet(3.303e+23, 2.4397e6);
    public static VENUS = new Planet(4.869e+24, 6.0518e6);
    ...
    
    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;
    }
    
    ...
}

第二次编辑

这是一种实现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;
    }

谢谢!已点赞。可能会选择这个答案作为采纳的答案。我们是否还应该通过类似私有构造函数的方式来防止创建任意实例? - KarolDepka
1
这取决于您和您从“enums”中需要什么。请检查我的修订答案,我添加了类似于Java中的Planet.values()方法。 - Nitzan Tomer
1
将其添加到我的答案中。 - Nitzan Tomer
1
@schrobe VALUES 成员是私有的,因此在使用 TypeScript 时无法更改它(当然,在运行时使用 JavaScript 可以)。但是通过 Planet.values() 方法可以访问到该成员。您可以返回值的克隆版本:return Planet.VALUES.slice(0); 或者您甚至可以使用不可变数组而不是常规数组。 - Nitzan Tomer
2
聪明。在我的情况下,'VALUES'的初始化必须在任何'new Planet'之前完成,否则当执行'Planet.VALUES.push(this)'时会出现'Cannot read properties of undefined (reading 'push')'的错误。这似乎很明显,所以我很惊讶没有人提到它。 - Flyout91
显示剩余8条评论

1

0
你可以使用 const 关键字得到“同样的东西”。
显然,这个解决方案并不完全像枚举那样,它只是使用 const 对象的键而不是实际枚举值的不同用法。
export const OrderStateEnum = {
    WAITING_SCORING: { key: 1, value: "WAITING for SCORING" },
    WAITING_ACCEPTANCE: { key: 2, value: "Waiting for acceptance" },
    ORDER_ACCEPTED: { key: 3, value: "Order accepted" },
 } as const

export type OrderStateEnum = keyof typeof OrderStateEnum

export function valueOf(value: string): OrderStateEnum{
    for(var key in OrderStateEnum) {
        if(value.toLowerCase()=== OrderStateEnum[key].value.toLowerCase()){
            return OrderStateEnum[key];
        }
    }
}

获取 false 枚举的所有值:

  states = OrderStateEnum;

要获取 false 枚举的某个值:

  OrderStateEnum.WAITING_SCORING.value;

以下是使用 *ngFor 的示例

<select formControlName="statoOrdine" [(ngModel)]="stato">
    <option *ngFor="let item of states | keyvalue" [value]="item.value.key"> 
      {{item.value.value}}</option>
</select>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接