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 呢?
这...... 这么折腾,目的是何?或者换个说法,优点是什么?
1
Jeremial 2020-05-11 09:03:57 +08:00
我理解是用的时候, 如果在冒号后面是当做类型来用, 其他情况当做值来用.
|
2
Hypn0s 2020-05-11 09:17:52 +08:00 via iPhone
类型是可传递的,不然经过函数倒一手就是普通的 string 了
|
3
wszgrcy 2020-05-11 09:36:31 +08:00 via Android
jquery 函数和 jquery 对象,应该好理解吧?
|
4
mxT52CRuqR6o5 2020-05-11 09:48:49 +08:00 via Android
为了显式告诉 typescript 类型系统这个变量是个内容特定的字符串,而不是单纯的 string 。
有其他写法可以更简单的达到目的 |
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 比较好用,特别是作为函数返回值的话,如果像上面假设的推断成具体字符串,那几乎每个返回字符串字面量的函数都要手写签名才行。 所以因为我们没有用平行宇宙的版本,就只能写两遍了。 |
6
vanishcode 2020-05-11 09:50:50 +08:00
!()[https://p4.ssl.qhimg.com/t01fde1cdffa3a6c5f3.png]
编译后 !()[https://p0.ssl.qhimg.com/t01880cdfcbf79d037f.png] 这个例子可能不是很严谨 |
7
momocraft 2020-05-11 09:59:18 +08:00
可能没特别目的, 只是配合设计
TS 设计 value 和 type 是不同 namespace. 另一个例子: export class A 的时候其实也同时 export 了 value (constructor) 和 type (instance) |
8
SilentDepth 2020-05-11 10:19:57 +08:00
TypeScript 有两个标识符空间,一个是普通 ES 的,一个是 TS 类型的。两个空间(通常)互不影响,也无法直接交互。于是当你想把 "Feature.INSTALL_PLUGIN_DIALOG" 这个字符串值单独作为类型(而不是视为普通的字符串)时就需要那么写了。
|
9
bnm965321 2020-05-11 10:43:57 +08:00
楼上有几位没有看懂,楼主说的是 类型名 /变量名 是一样的。
这种用法真的见过比较少,很多代码的 type 是用匈牙利命名法 |
10
yazoox OP |
11
yazoox OP @mxT52CRuqR6o5 兄弟,能多分享一点,你提到的“有其他写法可以更简单的达到目的”么?
thx |
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 |
13
mxT52CRuqR6o5 2020-05-11 11:42:34 +08:00
```
export const INSTALL_PLUGIN_DIALOG = "Feature.INSTALL_PLUGIN_DIALOG" as const; ``` |
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; 前面那个回复少了一句,少下面那句对外使用语义有些区别 |
15
Austaras 2020-05-11 14:23:45 +08:00
这个是古代的做法, 当代直接 as const 就 i 完了
|
16
azh7138m 2020-05-11 15:33:28 +08:00 via Android
楼上分析的挺好。。。
可是 as const 出来大半年了。。。 |
17
Exin 2020-05-11 16:46:01 +08:00
这做法一点也不少见,如果 OOP 的话,每个 class 都既是 type 也是 term 。
|
18
weixiangzhe 2020-05-11 22:19:56 +08:00
typescript 里有 const xxx = xxx as const 加一
|