距 typescript 3.7
正式发布已经有一段时间了,这段时间正在对手上的项目进行 typescript
的迁移工做,因此会特别留意每一次的 release
。javascript
对于 3.7
中包含的新特性,其实相比较以前几回 release
来讲,算是一个比较小的发布版本,可是其中包含的几个特性对代码质量自己,会带来显著地提高。java
首先第一个特性是对于 optional chaining
操做符的支持,翻译过来应该能够叫作可选链操做符,固然我仍是以为这样翻译有点怪怪的,暂且就直接用英文好了。typescript
这个特性首先是 es2019
中包含的一个新特性,对于特性自己,有兴趣的能够参考这里 。json
因为 typescript
是 javascript
的超集,因此预先实现这个特性也是在预料以内的事情,大概使用方式是这样的:安全
a?.b();
复制代码
等价于:bash
if(a) a.b();
// 或者
a && a.b()
复制代码
若是是多层嵌套,好比 b
也是一个对象,要继续调用 c()
,那么能够这样:ui
a?.b?.c()
复制代码
但其实就算这样写的话,它也不是安全的,由于 b()
中的 b
也有多是空值,直接调用的话,也会抛出异常。为了绝对的安全,能够这样写:spa
a?.b?.();
复制代码
值得注意的是,这里必定要对于可选的含义有一个正确的理解,可选的意思是,它在类型的声明中,经过 ?
来修饰,表明一个类型包含某个可为空值的属性。言外之意的意思就是,?.
不会对那些不符合类型声明自己的属性调用,好比:翻译
interface A {}
const a: A = {};
a?.b?.(); // Property 'b' does not exist on type 'A'
复制代码
除非 A
接口的声明改成:debug
interface A {
b?: any
}
复制代码
这个特性在项目的实践意义是很大的,咱们能够写更少的 if
断言语句或者 &&
操做符,可是却达到了相同的效果。
中文翻译过来会叫作双问号操做符,这个其实挺形象的,由于它的语法确实就是 ??
。
这个操做符的功能,往简单说,就是为一个空值,指定一个默认值,相似下面的代码:
let a = b || 'foo'
复制代码
当 b
为空值时,因为 ||
操做符的特性,a
的值会被赋予 foo
。若是使用 ??
操做符进行改写,以下:
let a = b ?? 'foo'
复制代码
表面上看,彷佛二者没什么区别,但其实这里隐含了一个问题,就是 ||
对于空值的概念,并不只仅指 null
和 undefined
,相似 false
、0
等一系列逻辑上为 false
的值都会算做空值,这显然是有问题的,好比:
const b = 0
let a = b || 'foo'
// a 为 'foo'
复制代码
这个示例中,咱们指望 a
只有在 b
为真正意义上的空值(null
或者 undefined
)时,才被赋予默认值,a
应当等于 0
,而实际运行结果确实 foo
,由于 b=0
,在 ||
操做符的运行过程当中,它会被解释为 false
。我曾在实际项目中,编写过一个验证码组件,很不幸,踩上了这个坑,当时为了 debug
这个问题,花了很长时间。
但使用 ??
操做符,就不会存在这个问题。
我相信不少人都曾经遇过相似的问题,由于缺少有效的命名规范,断言属性和断言方法会在实际项目中被混用,好比:
class A {
isFoo(): boolean {
return false;
}
}
function test(a: A) {
if (a.isFoo) {
...
}
}
复制代码
这里若是咱们的本意是要经过调用 a.isFoo
来获取一个断言值,咱们明显犯了一个错误,咱们应当使用 if (a.isFoo())
,而不是直接 if (a.isFoo)
,由于后者虽然在语法层面没有错误,可是在逻辑含义,它将被断言为 true
。但在 3.7
发布以后,typescript
会尝试帮助咱们发现这个问题。
虽然如此,但我仍然建议你们针对断言方法和断言属性制定统一的命名规范,好比 isXXX
表明属性,而 assertXXX
表明方法。
其余的一些变动,均是易用性上的一些改变,好比:
Flatter Error Reporting
:会将一大段的类型重复的错误日志,尽量地压缩为单条、更准确、更精简的错误日志@ts-nocheck
:以前版本中该注解仅支持行内级别json
类型js
文件提供 declaration
支持,以减少从 js
项目迁移的迁移成本关注公众号 全栈 101
,只谈技术,不谈人生