【问题标题】:TypeScript: add more data to enumTypeScript:向枚举添加更多数据
【发布时间】:2017-04-12 17:30:38
【问题描述】:

在 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();
    }
    // ...
}

【问题讨论】:

    标签: java typescript enums


    【解决方案1】:

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

    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)

    在java中为枚举中的每个项目创建一个静态实例,这意味着这确实做了同样的事情,只是java有更好的语法来定义枚举。


    编辑

    这是一个具有等效 Planet.values() 的版本,java 将生成:

    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;
        }
    
        ...
    }
    

    第二次编辑

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

    【讨论】:

    • 谢谢!赞成。可能会选择这个答案作为接受。我们是否还应该通过私有构造函数之类的方法来防止创建任意实例?
    • 确实如此。伟大的!对不起,我没有注意到。谢谢!
    • 这取决于您以及您对“枚举”的要求。检查我修改后的答案,我添加了 Planet.values() 方法,就像你在 java 中得到的一样。
    • 添加到我的回答中
    • @schrobe VALUES 成员是私有的,因此使用打字稿您无法更改它(显然在运行时使用 js 可以)。但是Planet.values() 你可以。您可以返回值的克隆:return Planet.VALUES.slice(0);,或者您甚至可以使用不可变数组而不是常规数组。
    【解决方案2】:

    很遗憾,这是不可能的。您可以只分配属性名称

    请参阅此参考以了解 TypeScript 规范 https://github.com/microsoft/TypeScript/blob/30cb20434a6b117e007a4959b2a7c16489f86069/doc/spec-ARCHIVED.md#a7-enums

    【讨论】:

      【解决方案3】:

      您可以使用 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];
              }
          }
      }
      

      接收假枚举的所有值:

        states = OrderStateEnum;
      

      要接收某个值的假枚举:

        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>
      

      【讨论】:

        猜你喜欢
        • 2015-03-24
        • 2020-05-11
        • 1970-01-01
        • 1970-01-01
        • 2020-12-24
        • 1970-01-01
        • 2011-08-17
        • 2022-01-18
        • 2013-10-14
        相关资源
        最近更新 更多