上周微软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官网文档。
领取专属 10元无门槛券
私享最新 技术干货