簡體   English   中英

使用對象字面量作為 TypeScript 枚舉值

[英]Use object literal as TypeScript enum values

我有一個枚舉:

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

但在這里我想使用一些值對:例如SMALL我想說它的key0value 100 我努力使用:

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

但是 TypeScript 不接受這個。 我怎樣才能做到這一點?

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()覆蓋,您還可以從對象中隱式打印枚舉名稱/鍵:

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

更新:在下面找到@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};
    }
}

Typescript 3.4 開始,您可以使用keyof typeofconst斷言的組合來創建可以與枚舉具有相同類型安全性的對象,並且仍然可以保存復雜的值。

通過創建與const同名的type ,您可以進行與普通枚舉相同的詳盡檢查。

唯一的缺點是您需要復雜對象中的一些鍵(我在這里使用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'
    }
}

在其他文件中,這可以簡單地使用,只需導入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)

我認為要達到你想要的,這樣的事情會起作用

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"

嘗試使用:

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

Object.freeze 使其只讀並防止添加更多屬性:

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

您可以使用類型化的 const 來實現此目的:

export const PizzaSize: {
    [key: string]: { key: string, value: string };
} = {
    SMALL: { key: 'key', value: 'value' }
};

您可以選擇將類型信息提取到單獨的接口聲明中:


interface PizzaSizeEnumInstance {
    key: string;
    value: string;
}

interface PizzaSizeEnum {
    [key: string]: PizzaSizeEnumInstance;
}

export const PizzaSize: PizzaSizeEnum = {
    SMALL: { key: 'key', value: 'value' }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM