第217题:TypeScript 中 ?.、??、!.、_、** 等符号的含义?
TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。TypeScript 通过 TypeScript 编译器或 Babel 转译为 JavaScript 代码,可运行在任何浏览器,任何操作系统。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
盘点 TypeScript 中我们常用的那些神奇符号
?. 可选链(Optional Chaining)
ES11(ES2020)新增的特性,TypeScript 3.7 支持了这个特性
可选链可让我们在查询具有多层级的对象时,不再需要进行冗余的各种前置校验:
又或是这种
很容易命中
Uncaught TypeError: Cannot read property...
用了 Optional Chaining ,上面代码会变成
TypeScript 在尝试访问
user.info
前,会先尝试访问user
,user
既不是null
也不是undefined
才会继续往下访问,如果user
是null
或者undefined
,则表达式直接返回undefined
即可选链是一种先检查属性是否存在,再尝试访问该属性的运算符 (
?.
)目前,可选链支持以下语法操作:
?? 空值合并运算符(Nullish coalescing Operator)
ES12(ES2021)新增的特性,TypeScript 3.7 支持了这个特性,当左侧的操作数为
null
或者undefined
时,返回其右侧操作数,否则返回左侧操作数。与逻辑或操作符(
||
) 不同,||
会在左侧操作数为 falsy 值(例如,''
或0
)时返回右侧操作数。也就是说,如果使用||
来为某些变量设置默认值,可能会遇到意料之外的行为:?: 可选参数和属性
TypeScript 特有的,在 TypeScript 2.0 支持了这个特性,可选参数和属性会自动把
undefined
添加到他们的类型中,即使他们的类型注解明确不包含undefined
。例如,下面两个类型是完全相同的:在TypeScript里,我们使用
?:
最多的情况是在接口中,通常:其中
point
中的两个属性x
、y
都是必须的,如果赋值时缺少任意一个就会报错:但接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 所以,这里就需要可选属性(
?.
),即属性是可选的在 TypeScript 有两个内置的工具泛型可以帮助我们处理接口的可选操作:
Partial
:把接口中的所有属性变成可选的Required
:将接口中所有可选的属性改为必须的Partial
Partial
的作用即把类型中的所有属性变成可选的例如:
它具体是如何实现的喃?
首先了解
keyof
,keyof
指的是把我们一个对象里面的键值对里的键(key
)一一罗列出来,并把它们联合起来形成一种联合类型:in
是遍历的作用,P in keyof T
把keyof T
进行一个个遍历并且每个都单独拿出来生成新的 "键值对"所以:
因此,实现了
Partial
的效果Required
Required
的作用刚好与Partial
相反,就是将接口中所有可选的属性改为必须的,区别就是把Partial
里面的?
替换成了-?
例如:
! 非空断言操作符
TypeScript 特有的,在 TypeScript 2.0 支持了这个特性,在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符
!
可以用于断言操作对象是非null
和非undefined
类型的。具体而言,运算x!
产生一个不包含null
和undefined
的x
的值。仅仅只是骗过了编译器,当你调用
sayHello()
依然会报错,这样使用是因为你已经断言了hello
一定是string
非空断言操作符 与 类型守卫
类型守卫用于确保该类型在一定的范围内,常用
typeof
、instanceof
、in
等但如果你这样写:
就会报错,即使
isSay
被分配到了类型守卫值,TypeScript 也只会丢失该信息。所以我们一般会const hi = hello!.toLowerCase()
加上非空断言操作符但 TypeScript 4.4 RC 会修复这个问题,如果你遇到这个问题,可升级到 TypeScript 4.4 版本后
_ 数字分隔符(Numeric separators)
ES12(ES2021)新增的特性,TypeScript 2.7 就已经支持了这个特性, 这个特性允许用户在数字之间使用下划线
_
来对数字分组。需要注意的是以下函数是不支持分隔符:
Number()
parseInt()
parseFloat()
** 指数操作符
ES7(ES2016)新增的特性
& 交叉类型(Intersection Types)
在 TypeScript 中,交叉类型是将多个类型合并为一个类型,我们可以通过
&
把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性如果多个类型中存在相同的属性喃?
这里
z
为什么会是never
类型喃?因为string & number
的值是永不存在的值,即never
而这样是可以的,所以,即多个类型合并为一个交叉类型时,如果多个类型间存在同名基础类型属性时,合并后的同名基础类型属性为
never
,如果同名属性均为非基础类型,则可以成功合并| 联合类型(Union Types)
联合类型表示一个值可以是几种类型之一,用竖线(
|
)分隔每个类型,所以number | string | boolean
表示一个值可以是number
,string
,或boolean
联合类型通常与
null
或undefined
一起使用:你也可以这么用:
原文
第一,没有
!.
只有!
。第二,除了!
,其它都是js的(?.
是为ts而设计出来的 ),说是typescript中有点不太合适,勉强也算对吧。?.
是可选链
,可以看成是高级的.
。比如a?.b
,当a是undefined时,直接返回undefined,不会再去.b
了。当a是对象时,就会直接.b
并返回b的值。??
是空值合并运算符
,可以看成是高级的||
。比||
高级在于:除了null和undefined,都属于空值,不再像||
一样不能区分false,'',0了。!
有点像 typescript 中的as
。比如let a: undefined | {a: 1} = xxxxx; let b: number = a!.a
,是为了缩小类型检查范围,告诉ide这个变量不为null或undefined。而
!.
只是!
和.
的组合罢了。_
是可以看成是特殊的语法糖,或者不算语法糖,只是为了方便读数字。比如 100000000 === 1_0000_0000。**
是幂运算符。3**2 === 9。