在typescript枚举中使用object

Vah*_*yan 34 enums typescript angular

我有一个枚举:

 export enum PizzaSize {
          SMALL =  0,
          MEDIUM = 1,
          LARGE = 2

    }
Run Code Online (Sandbox Code Playgroud)

但是在这里我想使用一些值:例如SMALL我想说它有2个值(0,100).我怎么能这样做?

我努力使用

export enum PizzaSize {
          SMALL =  {key:key, value: value},
         ...

    }
Run Code Online (Sandbox Code Playgroud)

但是打字稿不接受这个.

Jav*_*ome 47

TypeScript仅支持基于数字或基于字符串的枚举,因此您必须使用类来模拟对象枚举(这将允许您将其用作函数声明中的类型):

export class PizzaSize {
  static readonly SMALL  = new PizzaSize('SMALL', 'A small pizza');
  static readonly MEDIUM = new PizzaSize('MEDIUM', 'A medium pizza');
  static readonly LARGE  = new PizzaSize('LARGE', 'A large pizza');

  // private to disallow creating other instances of this type
  private constructor(private readonly key: string, public readonly value: any) {
  }

  toString() {
    return this.key;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以使用预定义的实例来访问它们value:

const mediumVal = PizzaSize.MEDIUM.value;
Run Code Online (Sandbox Code Playgroud)

或者您可能想要在其中定义的任何其他属性/属性类型PizzaSize.

并且由于toString()覆盖,您还可以从对象隐式打印枚举名称/键:

console.log(PizzaSize.MEDIUM);  // prints 'MEDIUM'
Run Code Online (Sandbox Code Playgroud)

  • 比接受的答案更优雅但是,构造函数应该是私有构造函数(私钥:字符串,PUBLIC值:任何){}才能使用PizzaSize.MEDIUM.value或定义一个getter到它 (2认同)
  • 如果您使用“ Ramda” /`lodash`克隆对象,例如“ R.clone({pizza:PizzaSize.MEDIUM})”或“ _.cloneDeep”,请谨慎使用此方法。三重等于和`switch`语句无法像使用TypeScript`enum`一样工作 (2认同)

Ben*_*Ben 23

我认为要达到你想要的效果,这样的事情会起作用

interface PizzaInfo {
  name: string;
  cost_multiplier: number;
}

enum PizzaSize {
  SMALL,
  MEDIUM,
  LARGE,
}

const pizzas: Record<PizzaSize, PizzaInfo> = {
  [PizzaSize.SMALL]: { name: "Small", cost_multiplier: 0.7 },
  [PizzaSize.MEDIUM]: { name: "Medium", cost_multiplier: 1.0 },
  [PizzaSize.LARGE]: { name: "Large", cost_multiplier: 1.5 },
};

const order = PizzaSize.SMALL;
console.log(pizzas[order].name);  // "Small"
Run Code Online (Sandbox Code Playgroud)


Joe*_*Tse 15

更新:在下面找到@Javarome的答案,这更优雅.我建议用他的方式.

如果您需要使用Type,请尝试添加一些代码.用法:getPizzSizeSpec(PizzaSize.small).value

enum PizzaSize {
    small,
    medium,
    large
}
interface PizzaSizeSpec {
    key: number,
    value: number
}
function getPizzaSizeSpec(pizzaSize: PizzaSize): PizzaSizeSpec {
    switch (pizzaSize) {
        case PizzaSize.small:
            return {key:0, value: 25};
        case PizzaSize.medium:
            return {key:0, value: 35};
        case PizzaSize.large:
            return {key:0, value: 50};
    }
}
Run Code Online (Sandbox Code Playgroud)


dan*_*y74 5

Object.freeze 使其只读并阻止添加更多属性:

const pizzaSize = Object.freeze({
  small: { key: 0, value: 25 },
  medium: { key: 1, value: 35 },
  large: { key: 2, value: 50 }
})
Run Code Online (Sandbox Code Playgroud)


bla*_*neh 5

Typescript 3.4开始,您可以使用keyof typeofconst断言的组合来创建对象,这些对象可以具有与枚举相同的类型安全性,并且仍保留复杂的值。

通过创建type与相同的名称const,您可以进行与普通枚举相同的穷举检查。

唯一的缺点是,您需要在复杂对象中使用一些键(我在value这里使用)来保存枚举成员的名称(如果有人可以找出可以以类型安全的方式构建这些对象的辅助函数,我会很高兴看到它!我无法工作)。

export const PizzaSize = {
    small: { value: 'small', key: 0, size: 25 },
    medium: { value: 'medium', key: 1, size: 35 },
    large: { value: 'large', key: 2, size: 50 },
} as const

export type PizzaSize = keyof typeof PizzaSize

// if you remove any of these cases, the function won't compile
// because it can't guarantee that you've returned a string
export function order(p: PizzaSize): string {
    switch (p) {
        case PizzaSize.small.value: return 'just for show'
        case PizzaSize.medium.value: return 'just for show'
        case PizzaSize.large.value: return 'just for show'
    }
}

// you can also just hardcode the strings,
// they'll be type checked
export function order(p: PizzaSize): string {
    switch (p) {
        case 'small': return 'just for show'
        case 'medium': return 'just for show'
        case 'large': return 'just for show'
    }
}
Run Code Online (Sandbox Code Playgroud)

在其他文件中,可以简单地使用它,只需import即可PizzaSize

import { PizzaSize } from './pizza'

console.log(PizzaSize.small.key)

type Order = { size: PizzaSize, person: string }
Run Code Online (Sandbox Code Playgroud)

还要注意,即使是通常可变的对象也无法使用as const语法进行突变。

const Thing = {
    ONE: { one: [1, 2, 3] }
} as const

// this won't compile!! Yay!!
Thing.ONE.one.splice(1, 0, 0)
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,我的 tsc `3.9.7` 正在抱怨 `order(PizzaSize.large)` 和 `Argument of type '{ readonly value: "large"; 只读键:2;只读大小:50;}' 不可分配给类型为 '"small" | 的参数 “中”| “大”'`。所以它的行为不像枚举那样。 (2认同)