Использовать объект в typescript перечислении

У меня есть перечисление:

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

    }

Но здесь я хотел бы использовать пару значений: например. SMALL я бы хотел сказать, что он имеет 2 значения (0, 100). Как я могу сделать это?

Я стараюсь использовать

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

    }

Но typescript не принимает этот.

Ответ 1

Обновление: найдите ответ @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};
    }
}

Ответ 2

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

тогда вы можете использовать предопределенные экземпляры для доступа к их value:

const mediumVal = PizzaSize.MEDIUM.value;

или любой другой тип свойства/свойства, который вы можете определить в PizzaSize.

и благодаря переопределению toString() вы также сможете неявно печатать имя/ключ enum из объекта:

console.log(PizzaSize.MEDIUM);  // prints 'MEDIUM'

Ответ 3

Попробуйте использовать:

const pizzaSize = {
    small: { key: 0, value: 25 },
    medium: { key: 1, value: 35 },
    large: { key: 2, value: 50 }
}

Ответ 4

Начиная с Typescript 3.4, вы можете использовать комбинацию утверждений keyof typeof и const для создания объектов, которые могут иметь такую же безопасность типов, что и перечисления, и при этом содержать сложные значения.

Создавая type с тем же именем, что и const, вы можете иметь те же проверки исчерпываемости, что и обычные перечисления.

Единственная проблема заключается в том, что вам нужен какой-то ключ в сложном объекте (здесь я использую value) для хранения имени члена enum (если кто-то может выяснить вспомогательную функцию, которая может создавать эти объекты безопасным способом, Я хотел бы увидеть это! Я не мог заставить работать).

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'
    }
}

В других файлах это можно использовать просто, просто импортируйте PizzaSize.

import { PizzaSize } from './pizza'

console.log(PizzaSize.small.key)

type Order = { size: PizzaSize, person: string }

Также обратите внимание, что даже объекты, которые обычно являются изменяемыми, не могут быть изменены с помощью синтаксиса as const.

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

// this won't compile!! Yay!!
Thing.ONE.one.splice(1, 0, 0)

Ответ 5

Object.freeze делает его доступным только для чтения и предотвращает добавление дополнительных свойств:

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