TypeScript 3.6发布,新功能尝鲜看

上周微软Devblog宣布发布TypeScript 3.6。

TypeScript是delphi之父、.net之父,c#之父世界著名程序员爱德斯.海尔斯伯格领导开发、微软免费开源的一种替代JavaScript的语言。它通过添加静态类型,用增强编译编译时错误捕捉。其强大的编译器和Babel等工具套件可以将优雅编写的TypeScript代码转换为标准的ECMAScript JS代码,支持在JS运行环境下,比如任何浏览器运行。

TypeScript不光语法优雅还支持大量的编辑器和IDE工具,可以在众多的编辑器实现代码完成,重构和快速修复等功能提供支持。当然最好的还是微软系的VS和VSC。

TypeScript生态圈也相当完善,比如著名的前端框架Angular,Angular 2就完全用TypeScript完全重写。

说了这多TypeScript的介绍,现在进入主题介绍TypeScript 3.6的新功能。

更严格生成器

TypeScript 3.6引入了对迭代器和生成器函数的更严格的检查。早期版本中,生成器用户无法区分是否从生成器生成或返回值。

此外,生成器总会假设yield类型为any。

TypeScript 3.6中,检查器现在知道curr.value的正确类型应该是我们的第一个示例中的字符串,上一个示例中调用next()时会报错。由于新版本中Iterator和IteratorResult类型声明中增强,引入了一些新的类型参数,还新增加了一个Generator类型的生成器。

Iterator类型可以支持用户指定生成的类型,返回的类型以及next可接受的类型。

新的Generator类型是一个迭代器,它同时存在return和throw方法,并且也是可迭代的。

为了区分返回值和结果,TypeScript 3.6将IteratorResult类型转换为区分联合类型:

在直接处理迭代器时,我们可以适当地缩小迭代器的值。

为了正确表示可以调用next()传递给生成器的类型,TypeScript 3.6还支持在生成器函数体内推断出yield的某些用法。

也可以使用显式返回类型强制执行可以从yield表达式返回,生成和计算的值类型。下面示例中,next()只能用布尔值调用,并且根据done的值,value可以是字符串或数字。

结果为:0-9,Done

更准确的数组转换

在ES2015之前的目标中,对于for和of循环和数组扩展之类的结构说实话有点重。为此TypeScript默认使用更简单的emit,它只支持数组类型,并支持使用--downlevelIteration标志对其他类型迭代。通过此标志,emit代码更准确,但更大。

默认情况下—downlevelIteration被设置为关闭,效果很好,大多数以ES5为目标的用户一般都只会使用数组的迭代。但是,只支持数组的emit在某些边缘情况下也有差异。

比如以下示例:

[...Array(5)]

相当于以下数组。

undefined,undefined,undefined

但是,TypeScript会将原始代码转换为代码:

Array(5).slice();

这略有不同。Array(5)会生成一个长度为5的数组,是成员未定义属性

1 in [undefined,undefined,undefined] // true

1 in array(3) // false

当TypeScript调用slice()时,它还会创建一个尚未设置索引的数组。

TypeScript 3.6中午没有使用slice()和内置函数,而是引入了一个新的__spreadArrays辅助程序,可以准确地模拟ECMAScript 2015中--downlevelIteration之外的对象发生的行为。--downlevelIteration. __spreadArrays也可以在tslib中使用。

改进UX Promise

Promise是时下最常用的数据异步方法之一。但是面向Promise的API通常会让用户感到困惑。TypeScript 3.6引入了一些改进,以防止Promise的误用。

例如,在将Promise传递给另一个函数之前通常会忘记.then()或await。TypeScript的错误消息现在会明确的告知用户应该考虑使用await关键字。

// ~~~~~~~~~~~~~

// Argument of type 'Promise' is not assignable to parameter of type 'User'.

// ...

// Did you forget to use 'await'?

在await或.then()前试图访问方法也很常见。下面是另一个错误的示例:

即使用户不知道await,这些消息提供了更多相关的信息。

除了Promises上更好的错误消息提示以外,新版本还在某些情况下提供快速修复。

更好的Unicode支持

当转换到ES2015及更高版本时,TypeScript 3.6在标识符中提供对Unicode字符的更好支持。

const = "world";//以前不允许,现在支持'--target es2015'

system.JS中的import.meta支持

当模块转化目标设置为system时,TypeScript 3.6支持将import.meta转换为context.meta。

在环境上下文中允许get和set操作符

在以前的TypeScript版本中,不允许在环境上下文中使用get和set操作符(例如在declare-d类中,或在.d.ts文件中)。理由是,就这些属性的读写而言,操作符与属性没有区别。ECMAScript的类字段提议可能与现有的TypeScript版本有不同的行为,所以需要一种方法来传达这种不同的行为。

为此TypeScript 3.6中,支持用户可以环境上下文中编写getter和setter。

declare class Foo {

// TS 3.6+ 允许:

get x(): number;

set x(val: number): void;

}

在随后的TypeScript 3.7中编译器本身将利用此功能以便生成的.d.ts文件也支持get/set操作符。

环境类和函数可以合并

此前TypeScript在任何情况下合并类和函数都是错误的。现在,环境类和函数(具有declare修饰符的类/函数或.d.ts文件中的)可以合并。在新版本中下面代码是ok的:

对比,之前需要这样写:

新版本写法的优点是可以很容易地表达可调用的构造函数模式,同时还允许名称空间与这些声明合并。

在下一个版本TypeScript 3.7中,编译器将利用此功能从.js文件生成的.d.ts文件可以适当地捕获这些类似类的函数的可调用性和可构造性。

API对--build和—incremental的支持

TypeScript 3.0引入了对引用其他项目的支持,并使用--build标志以增量方式构建它们。此外,TypeScript 3.4引入了--incremental标志,用于保存有关历史编译的信息,仅重建某些文件。这些标志对于更灵活地构建项目和加速构建非常有用。但是,这些标志不适用于Gulp和Webpack等第三方构建工具。TypeScript 3.6版本公开了两组API操作项目引用和增量程序构建。

对于--incremental构建,用户可以利用createIncrementalProgram和createIncrementalCompilerHost API。用户还可以使用新公开的readBuilderProgram函数用此API生成的.tsbuildinfo文件中重新保存旧程序实例,该函数仅用于创建新程序(无法修改返回的实例,只用于其他create * Program函数中的oldProgram参数)。

为了利用项目引用,公开了一个新的createSolutionBuilder函数,它返回一个新类型SolutionBuilder的实例。

新的TypeScript Playground

TypeScript Playground新支持许多新选项,包括:

目标选项(允许用户从es5切换到es3,es2015,esnext等)

所有严格标志(包括strict)

支持纯JavaScript文件(使用allowJS和可选的checkJs)

智能分号感知

Visual Studio和Visual Studio Code等编辑器可以自动应用快速修复,重构和其他转换,例如自动从其他模块导入值。这些转换由TypeScript提供支持,旧版本的TypeScript会无条件地在每个语句的末尾添加分号。但是该行为可能不符合一些用户的风格指南,许多用户对编辑器自动插入分号感到不满。

TypeScript新版本提供足够智能,可以在应用自动添加时检测的文件是否使用了分号。如果文件通常缺少分号,则TypeScript不会自动添加分号。

更智能的自动Import

JavaScript有很多不同的模块语法或约定:ECMAScript标准;Node(CommonJS);AMD,System.js等等。在大多数情况下,TypeScript默认使用ECMAScript模块语法自动导入,这在某些具有不同编译器设置TypeScript项目中通常是不合适的,也不适用于在纯JavaScript和需要调用的Node项目中。

TypeScript 3.6现在更加智能地对比现有导入,然后进行自动导入。

突破性变化

命名为"constructor"的类成员为构造函数

根据ECMAScript规范,使用名为constructor的方法的类声明是构造函数,无论它们是使用标识符名称还是字符串名称声明。

class C {

"constructor"() {

console.log("I am the constructor now.");

}

}

唯一例外的是在计算属性中使用:

class D {

["constructor"]() {

console.log("I'm not a constructor - just a plain method!");

}

}

DOM更新

许多声明已在lib.dom.d.ts中删除或更改。这包括(但不限于)以下内容:

全局窗口不再定义为类型Window,而是将其定义为类型Window & typeof globalThis。在某些情况下,最好将其类型称为窗口类型;

GlobalFetch用WindowOrWorkerGlobalScope取代;

导航器上的某些非标准属性消失了;

experimental-webgl被webgl或webgl2取代;

如果您认为有错误的更改,请提出问题!

JSDoc注释不再合并

在JavaScript文件中,TypeScript只会在JSDoc注释之前立即查询以确定声明的类型。

/**

* @param arg

*/

/**

* oh, hi, were you trying to type something?

*/

function whoWritesFunctionsLikeThis(arg) {

// 'arg' has type 'any'

}

关键字不能包含转义字符

此前关键字允许包含转义字符。TypeScript 3.6将不再支持。

while (true) {

\u0063ontinue;

}

// ~~~~~~~~~~~~~

// error! Keywords cannot contain escape characters.

下载安装

可以通过NuGet获取它,或使用npm命令下载安装:

npm install -g typescript

更多文档和帮助请浏览typescriptlang.org官网文档。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190909A08N6900?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券