TypeScript实用技巧 Nominal Typing名义类型详解
Nominal Typing(名义类型)
概念解析
拓展应用
在Vue中的应用
Nominal Typing(名义类型) 概念解析意思是给一个类型附加上一个“名义”,从而防止结构类型在某些情况下由于类型结构相似而被错用。假设有如下代码:
interface Vector2D { x: number, y: number };
interface Vector3D { x: number, y: number, z: number };
function calc(vector: Vector2D): void;
const vector: Vector3D = { x: 1, y: 1, z: 1}
calc(vector) // 并没有抛出错误
看上去calc()
函数应该只能传入Vector2D
类型,但其实也可以传入Vector3D
,因为本质上Vector3D
是Vector2D
的子集。对于calc()
函数来说,传入的vector
变量的类型中只要同时具有x
、y
属性即可通过类型校验。
这种特性这在TS中被称为 Structual Typing(结构类型)。通常来说这会给我们的编码过程带来便利,但极端情况下,也可能不符合我们的预期。
假如严格规定函数只能传入Vector2D
类型而不能传入Vector3D
类型,那么在类型实现上,就可以使用 名义上的类型(Nominal Type),通过为原类型添加一个独有标识来区分彼此:
interface Vector2D { x: number, y: number, __type: '2d' };
interface Vector3D { x: number, y: number, z: number, __type: '3d' };
function calc(vector: Vector2D): void;
对于interface,我们可以直接为其增加标志属性,但 primitive types (原始类型) 要如何处理呢?答案是使用交叉类型,例如:
type Food = string & { _type: 'food' };
type Money = number & { _type: 'money' }
你可能会对最终类型有所疑问,但这样处理之后,他们依旧是原始类型。因为实际上原始类型最终都会解析成对应的 WrapperType (包裹类型),例如string → String
,number → Number
,就像在JS中一样。这意味着你可把它们当做原始类型使用:
const money = 100 as Money;
const bill = money * 1; // bill 仍然是 number 类型
虽然这样的使用方式显得不太优雅,甚至有些繁琐,但在某些情况下至少可以保证类型安全。假如你的类型系统中有许多 基础类型单元,那可能会非常有用。
拓展应用这样的类型虽然可以被当做原始类型使用,但本质上又不是纯粹的原始类型。我们可以利用这个特性,写出一些非常有趣和实用的类型。
例如在字面量枚举时,我们可以在限制预设值的同时,使用 基于原始类型拓展出来的名义类型 进行兜底,从而使得我们的类型能够在具备足够自由性的前提下,仍能享受到TypeScript的类型提示,如下:
可以看到,CustomLiteral
名义类型不但可以享受到Literal
字面量的类型提示,又能跳出枚举的限制,使用自定义字符串。倘若我们将Literal
和原始类型string
直接交叉:
联合类型的机制本质上是求并集,而求并集最终得到的类型将会是更加广泛而通用的string
,这使得我们反而使失去了字面量类型的推导。想要实现上述效果,就需要为string
类型赋予“名义”,使它不同于普通的原始类型,不再那么“广泛”,从而在求并集的时候,不至于被string
类型彻底拿捏。附上Typescript Playground。
其实在Vue3源码中也有很多 Nominal Typing 的例子,例如VNode
、Teleport
、KeepAlive
、Fragment
等等这些内置组件,他们的定义中都有一个标志变量用于区分。分别对应了__is_VNode
,__isTeleport
,__isKeepAlive
,__isFragment
。下图是KeepAlive
组件的声明,更多组件声明可以移步官方仓库查阅。
如果类型声明的位置处在函数入参上,为了防止与用户定义的属性产生冲突,通常会采用unique symbol
作为键值来构造名义类型,例如:
以上就是TypeScript实用技巧 Nominal Typing名义类型详解的详细内容,更多关于TypeScript名义类型Nominal Typing的资料请关注易知道(ezd.cc)其它相关文章!
相关内容
拖拉机类型游戏电脑|拖拉机小游戏单机版
拖拉机类型游戏电脑|拖拉机小游戏单机版,,拖拉机小游戏单机版...
3500元超额值学生娱乐结构的优化配置
3500元超额值学生娱乐结构的优化配置,,作为一个DIY的主流用户...
公共CPU接口类型的详细描述
公共CPU接口类型的详细描述,,我们知道CPU是电脑的大脑, CPU的...
主板类型百科全书(基于芯片分类)
主板类型百科全书(基于芯片分类),,电脑维修基础之主板型号熟悉,主...
win10突然黑屏假死图文详解win10开机黑屏解决办
win10突然黑屏假死图文详解win10开机黑屏解决办法,解决办法,...
笔记本电脑hdmi连接电视方法详解|笔记本HDMI怎
笔记本电脑hdmi连接电视方法详解|笔记本HDMI怎么连接电视,,1. ...
2345安全卫士安装使用详解
2345安全卫士安装使用详解,安全卫士, ...
论竞技比赛结构中的十种常见误区
论竞技比赛结构中的十种常见误区,,近年来,在中国电子竞技的发展...
C上的引导检查文件系统:文件的类型
C上的引导检查文件系统:文件的类型,,故障现象:系统检查启动检查...
电脑硬盘接|电脑硬盘接口类型怎么看
电脑硬盘接|电脑硬盘接口类型怎么看,,电脑硬盘接口类型怎么看...
如何查看电脑内存类型|如何查看电脑内存类型大
如何查看电脑内存类型|如何查看电脑内存类型大小,,如何查看电...
光波炉的正确使用方法详解
光波炉的正确使用方法详解,食物,格兰仕,光波炉的正确使用方法...
硬盘接口类型有哪些 固态硬盘接口哪种好
硬盘接口类型有哪些 固态硬盘接口哪种好,硬盘,接口,硬盘接口分...
wps演示插入架构图|wps中的ppt插入组织结构图
wps演示插入架构图|wps中的ppt插入组织结构图,插入,演示,架构...
我的世界领地指令大全?领地权限设置详解|我的世
我的世界领地指令大全?领地权限设置详解|我的世界领地移动权...