还记得我在《2020 年 JavaScript 状态调研报告小结》中提到的 2020 年寰球开发者最喜爱的 JavaScript 写法是什么吗?– 没错!TypeScript!。鉴于在我的项目中应用 TypeScript 的确有以下种种益处:
- 帮忙开发者在「运行时」而非「编译时」及时感知类型 / 语法错误(⚠️ 留神,TypeScript 并非万能,它并不能帮忙您捕获申请谬误或环境谬误);
- 联合编辑器,提供智能提醒,晋升开发体验;
- 很少被提及的一点:更容易让服务端程序员了解代码,不便前后端交换;
本篇文章将向您介绍 TypeScript 自 3.7 版本以来更新的一些实用个性,心愿您的代码能变得更加巩固,优雅。
1. 新反对个性
请留神,TypeScript 是 JavaScript 类型的超集,而非语法的超集,因而一些合乎 JavaScript 语法标准的代码,在 TypeScript 中却可能报错,例如:
let x = 1
x = 'hello world'
因而,在古代工具链中,TypeScript 编译器甚至不被用作编译出指定版本 JavaScript 的工具(这通常是 babel 的工作),而是作为一种更弱小的代码查看工具被应用。然而随着 TypeScript 版本的更新,一些新的 JavaScript 语法个性也逐步被 TypeScript 反对,这使得开发者在一些场景下能够解脱 babel 编译的过程,间接应用 TypeScript 编译生成最终的代码。
1.1 Optional Chaining & Nullish Coalescing
自 3.7 版本开始,TypeScript 反对了目前在 stage 4 阶段的 Optional Chaining,Nullish Coalescing 语法。
1.2 Private Fields && Namespace exports
自 3.8 版本开始,Typescript 反对了目前在 stage 3 阶段的 Private Fields 语法。(通过底层应用 WeakMap 数据结构,该语法使得 JavaScript 类真正意义上领有「公有属性」)
class Foo {#bar}
同时,该版本还反对了 namespace exports 语法:
export * as utils from './utils'
1.3 Inference of class field types
自 4.0 版本开始,TypeScript 反对主动推导 class 中的属性类型,无需再显示申明。
2. 新类型:元组
TypeScript 4.0 开始反对两种新的元组类型申明形式:
- Variadic tuple types(可变元组类型)
- Labeled tuple types(命名元组类型)
2.1 可变元组类型
type Foo<T extends any[]> = [boolean, ...T, boolean]
通过这种申明形式,咱们能够更准确的定义一个函数参数类型,在应用函数式编程时,这种定义形式就很有用。
2.2 命名元组类型
const Address = [string, number]
function setAddress(...args: Address) {// some code here}
当咱们这样定义函数入参后,在应用函数时,编辑器的智能提醒只会提醒咱们参数类型,失落了对参数含意的形容。为了改善这一点,咱们能够通过 Labeled tuple types,咱们能够这样定义参数:
const Address = [streetName: string, streetNumber: number]
function setAddress(...args: Address) {// some code here}
这样,在调用函数时,咱们的参数就取得了相应的语义,这使得代码更加容易保护。
3. 可递归调用类型
自 Typescript 3.7 开始,咱们终于取得了只用一条类型申明申明 JSON 数据的能力:
type JSONValue =
| string
| number
| boolean
| null
| JSONValue[]
| {[key: string]: JSONValue
}
4. 谬误和断言解决
4.1 // @ts-expect-error
TypeScript 3.9 给出了一个代替 // @ts-ignore
正文的计划:// @ts-expect-error
。
从字面上咱们不难理解为什么后者是更优的抉择:
- 显示申明了会报错的起因,而不只是一味的躲避查看;
- 向前兼容,将来如果 TypeScript 反对某语法导致不再报错,TypeScript 会被动提醒删除正文,这会让代码变得更加简洁;
4.2 unknown
类型
让咱们想想这段代码会最终打印出什么:
try {willThrowAnError()
} catch (err) {console.log(typeof err.message)
}
答案是 "string"
吗,并非如此!因为 err.message
的值有可能是 undefined
,甚至有可能在这里抛错,这取决于咱们的函数 willThrowAnError
外部是如何定义的:
// err.message => undefined
function willThrowAnError() {throw 'hello world'}
// err.message => throw an Error!
function willThrowAnError() {throw null}
尽管第二种状况简直不会产生,但这两个示例阐明了 catch
参数类型的不确定性(因而在 TypeScript 中,它的默认类型是 any
)。
因而,在 TypeScript 4.0 中,提供了 unknown
类型供咱们解决这些咱们「不晓得」的类型。不同于 any
类型,unknown
是 TypeScript 中的第一类型,能够在任何中央应用。
子曰:知之为知之,不知为不知。
4.3 Assertion functions
自 TypeScript 3.7 开始,反对基于 return/throw
的类型断言。
function assertIsArray(val: any): asserts val is any[] {if (!Array.isArray(val)) throw new Error(`${val} is not an array`)
}
这将让测试变得更加容易。
点击此处浏览相干文档
5. 模块
5.1 Type-only imports
自 TypeScript 3.8 开始,TypeScript 反对仅引入模块类型:
import type {SomeThing} from "./some-module.js";
export type {SomeThing};
这样做的益处在于,当某个模块中蕴含副作用代码时,用户如果间接引入模块,就会无意间执行副作用代码,但当通过申明只引入类型时,则防止了这个隐患。
点击此处浏览相干文档。
6. 小结
至此,本篇文章带您疾速浏览了 TypeScript 3.7 以来一些实用性强的新个性,不晓得您是否学有所获?TypeScript 将在 2021 年 5 月 25 日公布 4.3 版本,届时会新增哪些有意思的新个性?且听下回分解:)