# 1 引言 Typescript 3.2 发布了几个新特性,主要变化是类型检查更严格,对 ES6、ES7 一些时髦功能拓展了类型支持。 # 2 概要 下面挑一些相对重要配置介绍。 ## `strictBindCallApply` 对 `bind` `call` `apply` 更严格的类型检测。 比如如下可以检测出 `apply` 函数参数数量和类型的错误: ```typescript function foo(a: number, b: string): string { return a + b; } let a = foo.apply(undefined, [10]); // error: too few argumnts ``` 特别对一些 `react` 老代码,函数需要自己 `bind(this)`,在没有用箭头函数时,可能经常使用 `this.foo = this.foo.bind(this)`,这时类型可能会不准,但升级到 TS3.2 后,可以准确捕获到错误了。 ## Object spread 类型自动合并 现在 `Object spread` 类型可以自动合并了: ```typescript // Returns 'T & U' function merge(x: T, y: U) { return { ...x, ...y }; } ``` ## Object rest 类型自动剔除 ```typescript const { x, y, z, ...rest } = obj; ``` 当我们使用了 Object rest 语法时,`rest` 的类型其实是 `obj` 类型剔除了 `x` `y` `z` 这三个 key 的类型,现在 ts 已经能自动做到了! 下面是实现方式: ```typescript interface XYZ { x: any; y: any; z: any; } type DropXYZ = Pick>; function dropXYZ(obj: T): DropXYZ { let { x, y, z, ...rest } = obj; return rest; } ``` 通过 `Pick` & `Exclude` 达到剔除 obj 属性的效果,具体可以参考之前的精读:[精读《Typescript2.0 - 2.9》](https://github.com/dt-fe/weekly/blob/master/58.%E7%B2%BE%E8%AF%BB%E3%80%8ATypescript2.0%20-%202.9%E3%80%8B.md#%E5%AF%B9%E7%B1%BB%E5%9E%8B%E4%BF%AE%E9%A5%B0%E7%9A%84%E5%A2%9E%E5%BC%BA)。 ## tsconfig 配置集成支持 node_modules 这是一个福音,以往在 `tsconfig.json` 为了继承一个配置,我们需要这么写: ```json { "extends": "../node_modules/@my-team/tsconfig-base/tsconfig.json" } ``` TS3.2 内置了 node_modules 解析,因此就可以更清晰的描述了: ```json { "extends": "@my-team/tsconfig-base" } ``` ## 内置 BigInt 类型 新增了 `bigint` 类型,再也不会把 `bigint` 和 `number` 混淆了。 ```typescript declare let foo: number; declare let bar: bigint; foo = bar; // error: Type 'bigint' is not assignable to type 'number'. bar = foo; // error: Type 'number' is not assignable to type 'bigint'. ``` # 3 精读 这次改动意图非常明显,是为了跟上 JS 的新语法。随着 JS 规范发展,TS 类型必然要得到补充,像 Object spread 与 Object rest 在项目中使用已经非常普遍了,及时完善类型支持,有助于对项目类型的约束。 `strictBindCallApply` 基本可以算是对 React 社区的回馈。在 React 很早期的版本是支持函数自动 `bind` 的,后来觉得过于 magic 就移除了,由于当时没有箭头函数,大家只好在调用处 `.bind(this)` 一下。 后来有人发现 `.bind(this)` 会导致函数引用变化,对 Mutable 性能优化不友好,所以许多代码都在 `constructor` 位置进行类似 `this.fooBind = this.foo.bind(this)` 这样的赋值,如今 TS3.2 对这种 `bind` 过后的函数也具备了严格的类型推测,将会有一大批代码从中受益。 顺带一提,最近 Babel 7.2.0 发布,也带来了一些新特性支持,比如: 提前支持私有属性: ```javascript class Person { #age = 19; #increaseAge() { this.#age++; } birthday() { this.#increaseAge(); alert("Happy Birthday!"); } } ``` 提前支持 pipleline Operator: ```javascript const result = 2 |> double |> 3 + # |> toStringBase(2, #); // "111" ``` 整个 JS 生态一篇欣欣向荣的景象。不过 TS 对 ES 规范支持还是比较保守的,比如 Babel 6.x 就支持的 optional chain,现在也没有得到支持,原因是 “等待进入 Stage3”。追踪 ISSUE 可以参考:https://github.com/Microsoft/TypeScript/issues/16 如果不清楚 Stage3 的含义,可以阅读前端精读之前的一篇文章:[精读 TC39 与 ECMAScript 提案](https://github.com/dt-fe/weekly/blob/master/15.%E7%B2%BE%E8%AF%BB%20TC39%20%E4%B8%8E%20ECMAScript%20%E6%8F%90%E6%A1%88.md)。 # 4 总结 这次的版本升级几乎没带来什么新语法,只是纯粹的类型检测能力增强,所以如果希望进一步提高代码质量,就尽快升级把。 > 讨论地址是:[精读《Typescript 3.2 新特性》 · Issue #117 · dt-fe/weekly](https://github.com/dt-fe/weekly/issues/117) **如果你想参与讨论,请[点击这里](https://github.com/dt-fe/weekly),每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。**