V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
shilianmlxg
V2EX  ›  程序员

前端怎么定义字典更好呢

  •  1
     
  •   shilianmlxg · 2 天前 · 2872 次点击

    我需要一个字典,要有一下三点,并且后期可以扩展字段
    key 键名称(下面的 OR,PACU)
    value 值(下面的 1,2)
    label 值
    color 值(可选)

    现在定义的两个 一个 enum 一个 map 。觉得有点多余,

    问下最优解是什么,

    我希望通过访问字段的方式就能知道该字典所对应的值,比如 ROOM_TYPE_ENUM.OR

    export const enum ROOM_TYPE_ENUM {

    OR = 1, // 手术间

    PACU = 2 // 复苏室

    }



    export const ROOM_TYPE_MAP = [

    {

    label: '手术间',

    value: 1

    },

    {

    label: '复苏室',

    value: 2

    },

    ]

    29 条回复    2024-07-02 17:22:55 +08:00
    Moonless
        1
    Moonless  
       2 天前   ❤️ 1
    w568w
        2
    w568w  
       2 天前   ❤️ 1
    @Moonless

    @Livid AI 回复
    han3sui
        3
    han3sui  
       2 天前   ❤️ 3
    楼上这个有点过了吧,AI 回答感觉没什么问题啊,给出了明确的方案和解释,又不是瞎编的
    han3sui
        4
    han3sui  
       2 天前
    而且人家还特地贴了图进来,都不是直接复制粘贴
    superedlimited
        5
    superedlimited  
       2 天前 via iPhone   ❤️ 2
    @han3sui 网警是这样的。
    duzhuo
        6
    duzhuo  
       2 天前
    @han3sui 贴图才是最不好的,想测试都麻烦
    ZZITE
        7
    ZZITE  
       2 天前   ❤️ 3
    ```
    const ROOM_TYPE_KEYS = ["OR", "PACU"] as const;

    type RoomTypeMap = {
    [key in (typeof ROOM_TYPE_KEYS)[number]]: {
    label: string;
    value: number;
    color?: string;
    };
    };

    export const ROOM_TYPE_MAP: RoomTypeMap = {
    OR: {
    label: "手术间",
    value: 1,
    },
    PACU: {
    label: "复苏室",
    value: 2,
    },
    };
    ```

    我一般会这么写
    SimonOne
        8
    SimonOne  
       2 天前
    @han3sui #3 因为站长不让贴 AI 回复,这是个人站忘啦
    accelerator1
        9
    accelerator1  
       2 天前
    站长的想法是不要让 AI 回复充斥网站,而不是禁止 AI 工具的使用。
    楼主的问题的确可以 GPT 解决的,工具还是要学会使用的,我们公司招人,会不会 GPT 也是一项指标了。。。
    meteor957
        10
    meteor957  
       2 天前
    枚举不方便通过值去查询到对应的 key
    Moonless
        11
    Moonless  
       2 天前
    @w568w Sorry ,sorry ,觉着楼主的提问很合适直接对话,试了下结果又很合理,就贴了出来。AI 工具确实很方便😄,后续会留意。
    @han3sui @accelerator1 哈哈,确实是看了答案的合理性
    RogerL
        12
    RogerL  
       2 天前
    我跟 1L 的做法差不多,但是我建议用数组,然后通过 reduce 转换成对象。
    因为数组字典很多情况下你可能会做下拉展示,可能会对排序有需求
    dfkjgklfdjg
        13
    dfkjgklfdjg  
       2 天前
    @RogerL #12 ,我和你反过来,用对象然后用 `Object.values()` 转成数组去下拉展示。
    connection
        14
    connection  
       2 天前
    key string 用 object 定义
    paopjian
        15
    paopjian  
       2 天前
    学了八股文才知道不要乱用 Object 作为数组,不然容易飞出去找原型链,还是 map 安全点
    deepshe
        16
    deepshe  
       2 天前
    我也是用枚举类去转成数组, 判断下是不是数字类型,
    Object.entries(enumObj).map(([key, value]) => {
    if (isNaN(Number(key))) {
    arr.push({ label: key, value });
    }
    });
    xocus
        17
    xocus  
       2 天前
    写个 enum ,再写一个 dict 是好麻烦,但是我还是这样分开写 2 个,没找到好方法
    laobobo
        18
    laobobo  
       2 天前
    @w568w 有毛病啊,人家发个图也不行么
    rain0002009
        19
    rain0002009  
       2 天前
    export enum ROOM_TYPE {
    手术间 = 1,
    复苏室,
    }

    直接中文又能用又直观
    dingdangnao
        20
    dingdangnao  
       2 天前 via iPhone
    @rain0002009 #19 魔鬼!!😂😂
    retrocode
        21
    retrocode  
       2 天前
    一种方式是直接按静态类处理, 扩展性更好些. 任意自增方法或属性

    ```ts
    class TsEnum {
    public readonly code: string
    public readonly name: string
    constructor(code: string, name: string) {
    this.code = code
    this.name = name
    }
    public static getInstanceByCode<T extends TsEnum>(this: new (code: string, name: string) => T, code: string): T | null {
    const enumValues = Object.values(this)
    for (const enumValue of enumValues) {
    if (enumValue instanceof this && enumValue.code === code) {
    return enumValue
    }
    }
    return null
    }
    }

    class SystemEnum extends TsEnum {
    public static readonly FOO1 = new SystemEnum('foo1', 'FOO1')
    public static readonly FOO2 = new SystemEnum('foo2', 'FOO2')
    }

    console.log(SystemEnum.getInstanceByCode('foo1'))
    console.log(SystemEnum.FOO1.name)

    ```
    yangg
        22
    yangg  
       2 天前
    之前写过一个

    /**
    * @param {{ name: string, text: string, code?: number | string }[]} enums
    * @returns {[Object, {id: number | string, text: string}[]]}
    */
    function createEnum(enums) {
    const Enum = {}
    const options = []
    for (let i = 0; i < enums.length; i++) {
    const x = enums[i]
    const code = 'code' in x ? x.code : i + 1
    Enum[x.name] = code
    // Enum[code] = x.text // cannot use Object.values
    Object.defineProperty(Enum, code, {
    value: x.text,
    // implies enumerable: false
    })
    options.push({id: code, text: x.text})
    }
    Object.freeze(Enum)
    return [Enum, options]
    }
    yangg
        23
    yangg  
       2 天前   ❤️ 1
    使用
    export const [ContractType, ContractTypeOptions] = createEnum([
    { name: 'Standard', text: '标准合同', code: 1 },
    { name: 'NonStandard', text: '非标准合同', code: 0 },
    ])

    ContractType.Standard = 2 // ❌ throws a 'Error'.
    yangg
        24
    yangg  
       2 天前
    1. 方便直接从名称取值
    2. 同时方便下拉列表显示
    Livid
        25
    Livid  
    MOD
       1 天前
    @Moonless 请不要再把 AI 生成的回复发到这里。
    baoshijiagong
        26
    baoshijiagong  
       1 天前   ❤️ 1
    AI 回复当然存在问题,按照问题要求,已经用了 OR 作为对象的 key 了,那么不再需要 key 的属性,属于多此一举。AI 没有思考,程序员们解决问题避免用 AI 吧,AI 只是一个程序,可以参考,就像用 Google 一样。

    题主的问题也有错误,ROOM_TYPE_MAP 是个 Array ,这个命名牛头不对马嘴。

    作为回答,我觉得这样即可:
    export const enum ROOM_TYPE_ENUM {
    OR = {
    {
    label: '手术间',
    value: 1
    },
    },

    PACU = {
    label: '复苏室',
    value: 2
    },
    }

    value 都可以不需要,可以选加 color ,可以加 order ,来为下拉框排序
    baoshijiagong
        27
    baoshijiagong  
       1 天前
    补充:value 应该是传给后端的,还是需要。
    wzdsfl
        28
    wzdsfl  
       1 天前
    @w568w 你是不是魔怔了,这也要 @ 让他永 ban ?
    Moonless
        29
    Moonless  
       1 天前
    @Livid Sorry, 后续不会了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1469 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:51 · PVG 07:51 · LAX 16:51 · JFK 19:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.