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

reactjs, typescript 中定义 action type 时,经常看到一种使用方法, type & const 用同一个名字,不知其深意?

  •  
  •   yazoox · 2020-05-11 08:50:21 +08:00 · 2428 次点击
    这是一个创建于 1447 天前的主题,其中的信息可能已经有所发展或是发生改变。
    export type INSTALL_PLUGIN_DIALOG = "Feature.INSTALL_PLUGIN_DIALOG";
    export const INSTALL_PLUGIN_DIALOG: INSTALL_PLUGIN_DIALOG = "Feature.INSTALL_PLUGIN_DIALOG";
    

    如上所示。先定义了一个 type INSTALL_PLUGIN_DIALOG,其值可能是就是它自己“INSTALL_PLUGIN_DIALOG”, 或者一种变形“Feature.INSTALL_PLUGIN_DIALOG"。

    然后,又定义了一个 const,名字和类型一模一样,然后这个 const 的值和上面类型定义的那个值也是一模一样。

    关键是这个 type 和 const 还都 export 了。那么, 在其它文件里面 import {INSTALL_PLUGIN_DIALOG} from "<file_name>",到底引入的是 type 还是 const 呢?

    这...... 这么折腾,目的是何?或者换个说法,优点是什么?

    18 条回复    2020-05-11 22:19:56 +08:00
    Jeremial
        1
    Jeremial  
       2020-05-11 09:03:57 +08:00
    我理解是用的时候, 如果在冒号后面是当做类型来用, 其他情况当做值来用.
    Hypn0s
        2
    Hypn0s  
       2020-05-11 09:17:52 +08:00 via iPhone
    类型是可传递的,不然经过函数倒一手就是普通的 string 了
    wszgrcy
        3
    wszgrcy  
       2020-05-11 09:36:31 +08:00 via Android
    jquery 函数和 jquery 对象,应该好理解吧?
    mxT52CRuqR6o5
        4
    mxT52CRuqR6o5  
       2020-05-11 09:48:49 +08:00 via Android
    为了显式告诉 typescript 类型系统这个变量是个内容特定的字符串,而不是单纯的 string 。
    有其他写法可以更简单的达到目的
    namelosw
        5
    namelosw  
       2020-05-11 09:49:04 +08:00   ❤️ 3
    一个是类型(type),一个是值(term)。有的地方比如泛型或者签名需要 type 的时候就传 type,需要值的时候传的是 const 。TypeScript 自己能按上下文理解,所以同名的时候它自己就考眼力见判断了。

    比如 type Action = INSTALL_PLUGIN_DIALOG | OTHER_ACTION,这时候用的就是 type 。
    比如 if (action.type === INSTALL_PLUGIN_DIALOG),这时候用的就是 term 。
    少了一个这两个就会红一半。

    理论上本来其实写一个 const INSTALL_PLUGIN_DIALOG 就行,但是 TypeScript 为了让大部分人不会觉得特别奇怪,所以把这个类型推断泛化了,导致这个 case 写起来反而麻烦。
    你可以想象平行宇宙有个另外的 TypeScript 版本可以这样写:
    const INSTALL_PLUGIN_DIALOG = "Feature.INSTALL_PLUGIN_DIALOG"
    type Action = typeof INSTALL_PLUGIN_DIALOG | typeof OTHER_ACTION

    但是实际上这样写不行,因为 typeof INSTALL_PLUGIN_DIALOG 返回的类型是 string 而不是"Feature.INSTALL_PLUGIN_DIALOG"

    从具体到宽泛的角度来看,"Feature.INSTALL_PLUGIN_DIALOG"是一个 string,而 string 是一个 Object 。用极端的角度看,不然 typeof INSTALL_PLUGIN_DIALOG 应该是"Feature.INSTALL_PLUGIN_DIALOG",不然应该是 Object 。但是实践上还是推断成 string 比较好用,特别是作为函数返回值的话,如果像上面假设的推断成具体字符串,那几乎每个返回字符串字面量的函数都要手写签名才行。

    所以因为我们没有用平行宇宙的版本,就只能写两遍了。
    vanishcode
        6
    vanishcode  
       2020-05-11 09:50:50 +08:00
    momocraft
        7
    momocraft  
       2020-05-11 09:59:18 +08:00
    可能没特别目的, 只是配合设计

    TS 设计 value 和 type 是不同 namespace.

    另一个例子: export class A 的时候其实也同时 export 了 value (constructor) 和 type (instance)
    SilentDepth
        8
    SilentDepth  
       2020-05-11 10:19:57 +08:00
    TypeScript 有两个标识符空间,一个是普通 ES 的,一个是 TS 类型的。两个空间(通常)互不影响,也无法直接交互。于是当你想把 "Feature.INSTALL_PLUGIN_DIALOG" 这个字符串值单独作为类型(而不是视为普通的字符串)时就需要那么写了。
    bnm965321
        9
    bnm965321  
       2020-05-11 10:43:57 +08:00
    楼上有几位没有看懂,楼主说的是 类型名 /变量名 是一样的。

    这种用法真的见过比较少,很多代码的 type 是用匈牙利命名法
    yazoox
        10
    yazoox  
    OP
       2020-05-11 11:32:49 +08:00
    @bnm965321 兄弟,能多分享一些么?
    可能我们这边的已有项目,就是这么命名的。不知道你们有没有其它的命名方法,或许更容易阅读和理解一些。

    thx.
    yazoox
        11
    yazoox  
    OP
       2020-05-11 11:33:50 +08:00
    @mxT52CRuqR6o5 兄弟,能多分享一点,你提到的“有其他写法可以更简单的达到目的”么?
    thx
    bnm965321
        12
    bnm965321  
       2020-05-11 11:42:01 +08:00
    @yazoox 可以参考微软 FluentUI 的代码,他们是用匈牙利命名法,第一个大写的字母代表类型的种类。一般 action type 就是 AActionName

    https://developer.microsoft.com/en-us/fluentui#/controls/web/button
    mxT52CRuqR6o5
        13
    mxT52CRuqR6o5  
       2020-05-11 11:42:34 +08:00
    ```
    export const INSTALL_PLUGIN_DIALOG = "Feature.INSTALL_PLUGIN_DIALOG" as const;
    ```
    mxT52CRuqR6o5
        14
    mxT52CRuqR6o5  
       2020-05-11 12:48:14 +08:00
    @yazoox
    export const INSTALL_PLUGIN_DIALOG = "Feature.INSTALL_PLUGIN_DIALOG" as const;
    export type INSTALL_PLUGIN_DIALOG = typeof INSTALL_PLUGIN_DIALOG;

    前面那个回复少了一句,少下面那句对外使用语义有些区别
    Austaras
        15
    Austaras  
       2020-05-11 14:23:45 +08:00
    这个是古代的做法, 当代直接 as const 就 i 完了
    azh7138m
        16
    azh7138m  
       2020-05-11 15:33:28 +08:00 via Android
    楼上分析的挺好。。。
    可是 as const 出来大半年了。。。
    Exin
        17
    Exin  
       2020-05-11 16:46:01 +08:00
    这做法一点也不少见,如果 OOP 的话,每个 class 都既是 type 也是 term 。
    weixiangzhe
        18
    weixiangzhe  
       2020-05-11 22:19:56 +08:00
    typescript 里有 const xxx = xxx as const 加一
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1256 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 23:51 · PVG 07:51 · LAX 16:51 · JFK 19:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.