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

求解: typescript 如何根据 enum 的字符值返回对应的 enum 实例?

  •  
  •   hahaFck · 2023-05-15 09:39:29 +08:00 · 1818 次点击
    这是一个创建于 556 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如定义以下 enum

    const enum VerticalAlign {
       bottom, center, top
    }
    

    定义下面方法

    //data 是后台返回的数据
    function getVerticalAlign(data:JsonData):VerticalAlign {
    	let value:string|null = data['vAlign'];
        switch(value) {
        	case VerticalAlign.bottom:
            	return VerticalAlign.bottom;
            ........
        }
    }
    

    现在的写法就是每个 enum 的值都要判断一次然后返回,有通用的方法返回一个 enum 的值么,直接写 VerticalAlign[value] 编译器报错.

    23 条回复    2023-05-16 09:45:16 +08:00
    hahaFck
        1
    hahaFck  
    OP
       2023-05-15 09:41:24 +08:00
    上面的例子写的简单,enum 实际是数字类型的,不是字符串类型。
    t123yh
        2
    t123yh  
       2023-05-15 09:55:16 +08:00
    let s = "bottom";

    return VerticalAlign[s];
    hahaFck
        3
    hahaFck  
    OP
       2023-05-15 10:02:36 +08:00
    @t123yh 不行啊,s 是后台返回来的值,这个时候不知道是哪个呢
    devilte
        4
    devilte  
       2023-05-15 10:06:58 +08:00
    ```
    enum Position {
    Top,
    Right,
    Bottom,
    Left
    }

    const getPosition = (v: keyof typeof Position): Position=> {
    return Position[v];
    }

    getPosition('Bottom');

    ```
    是这个意思吧?
    NoManPlay
        5
    NoManPlay  
       2023-05-15 10:08:13 +08:00
    现在是要根据 value=0,返回对应的 bottom ,还是 value='bottom',获取对应的 0
    hahaFck
        6
    hahaFck  
    OP
       2023-05-15 10:20:57 +08:00
    @devilte
    @NoManPlay
    我的意思是,后台返回来的值 s ,有可能是 enum 中的值的任意一个,想写一个通用的方法,根据值(string | number)来返回对应的 enum 类型。
    NoManPlay
        7
    NoManPlay  
       2023-05-15 10:25:03 +08:00
    ```
    enum VerticalAlign {
    bottom,
    center,
    top,
    }

    function getVerticalAlign(value: any): VerticalAlign | null {
    if (value in VerticalAlign) {
    return VerticalAlign[value as keyof typeof VerticalAlign];
    } else {
    return null;
    }
    }
    getVerticalAlign('bottom'); // 0
    getVerticalAlign(''); // null
    console.log(getVerticalAlign(0)); // bottom

    ```
    debuggerx
        8
    debuggerx  
       2023-05-15 10:30:05 +08:00
    看看下面的比较结果:
    console.info(VerticalAlign['bottom'] === VerticalAlign.bottom);
    console.info(VerticalAlign['bottom1'] === VerticalAlign.bottom);

    所以这种会后台传的,一般这样搞:
    enum VerticalAlign {
    bottom, center, top, unknown
    }

    let alignStr = "from server";

    console.info(VerticalAlign[alignStr] ?? VerticalAlign.unknown);
    hahaFck
        9
    hahaFck  
    OP
       2023-05-15 10:35:39 +08:00
    @NoManPlay
    @debuggerx

    好的,多谢二位哈哈,知道怎么搞了
    hahaFck
        10
    hahaFck  
    OP
       2023-05-15 10:38:44 +08:00
    @debuggerx 不行啊,直接写 VerticalAlign[alignStr]报 No index signature with a parameter of type 'string' was found on type 'typeof VerticalAlign'.
    paledream
        11
    paledream  
       2023-05-15 10:49:05 +08:00
    ```typescript
    enum VerticalAlign {
    bottom = 1, center = 2, top = 3
    }

    type K = keyof typeof VerticalAlign

    function getVerticalAlign(data:any): VerticalAlign {
    let value: K = data['vAlign'];
    return VerticalAlign[value]
    }

    ```
    walpurgis
        12
    walpurgis  
       2023-05-15 11:40:41 +08:00
    enum 是 ts 编译时的东西,js 里没有 enum ,运行时从外部获取的数据,ts 没法保证类型安全,所以 OP 想要的效果无论如何都绕不开 any 或类型断言,而 type safe 的方法就是一个个判断
    mxT52CRuqR6o5
        13
    mxT52CRuqR6o5  
       2023-05-15 11:55:31 +08:00
    难道不应该是直接
    return value as any as VerticalAlign
    吗,怎么一堆 return VerticalAlign[value]的
    silk
        14
    silk  
       2023-05-15 11:57:41 +08:00
    为什么 JsonData 定义的时候不知道,等使用的时候才去做类型判断
    ysc3839
        15
    ysc3839  
       2023-05-15 13:26:14 +08:00 via Android
    @mxT52CRuqR6o5 楼主是要取 enum key string 对应的 value 吧?你这么转换类型结果还是 string
    mxT52CRuqR6o5
        17
    mxT52CRuqR6o5  
       2023-05-15 14:10:18 +08:00
    @ysc3839 OP 给的代码每个 case return 一个 enum 的 value ,联合起来函数返回的应该是整个的 enum value ,没问题啊
    假设现在有一个枚举
    enum E {A,B}
    type A = E.A|E.B 和 type B = E 应该是等价的
    uni
        18
    uni  
       2023-05-15 14:20:38 +08:00
    11 楼正解!
    就是在定义 enum 的时候赋好值
    enum VerticalAlign {
    bottom = 1, center = 2, top = 3
    }
    ysc3839
        19
    ysc3839  
       2023-05-15 15:28:05 +08:00 via Android
    @mxT52CRuqR6o5 但是这明显不符合一般用途,一般是获取到了 enum key string ,要转换成 enum value ,前面几楼给的代码也是这个逻辑,楼主也没反对。具体是什么需求需要楼主出来解释清楚。
    TWorldIsNButThis
        20
    TWorldIsNButThis  
       2023-05-15 15:29:19 +08:00 via iPhone
    不要用 enum
    这东西类型定义是坏的
    Lenic
        21
    Lenic  
       2023-05-15 17:51:36 +08:00
    type VerticalAlign = "bottom" | "center" | "top";

    不知道这样行不行,本质上你传进来的参数是字符串,到时候 as 一下就可以了

    const abc = data.vAlign as VerticalAlign;

    这样 abc 就是 VerticalAlign 类型的,但又是字符串类型的,是带有约束的字符串,即必须是 "bottom"、"center"、"top" 这三个字符串中的一个
    jsq2627
        22
    jsq2627  
       2023-05-16 03:44:06 +08:00 via iPhone
    ts 的 enum 有种说不上来的残废感
    hahaFck
        23
    hahaFck  
    OP
       2023-05-16 09:45:16 +08:00
    @ysc3839
    @mxT52CRuqR6o5

    已经放弃了,这东西怎么转换都麻烦,还是一个一个判断吧。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3137 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 00:38 · PVG 08:38 · LAX 16:38 · JFK 19:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.