Use object literal as TypeScript enum values

前端 未结 6 1326
星月不相逢
星月不相逢 2020-12-29 17:54

I have an enum:

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

But here I\'d like t

6条回答
  •  心在旅途
    2020-12-29 18:34

    As of Typescript 3.4, you can use a combination of keyof typeof and const assertions to create objects that can have the same type safety as enums, and still hold complex values.

    By creating a type with the same name as the const, you can have the same exhaustiveness checks that normal enums have.

    The only wart is that you need some key in the complex object (I'm using value here) to hold the name of the enum member (if anyone can figure out a helper function that can build these objects in a typesafe way, I'd love to see it! I couldn't get one working).

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

    In other files this can be used simply, just import PizzaSize.

    import { PizzaSize } from './pizza'
    
    console.log(PizzaSize.small.key)
    
    type Order = { size: PizzaSize, person: string }
    

    Also notice how even objects that are usually mutable can't be mutated with the as const syntax.

    const Thing = {
        ONE: { one: [1, 2, 3] }
    } as const
    
    // this won't compile!! Yay!!
    Thing.ONE.one.splice(1, 0, 0)
    

提交回复
热议问题