写点什么

TypeScript 3.6 正式发布!新增 4 项突破性特点

  • 2019-09-03
  • 本文字数:6151 字

    阅读完需:约 20 分钟

TypeScript 3.6正式发布!新增4项突破性特点

8 月 28 日微软正式发布了 TypeScript 3.6 版,本文将主要介绍 TypeScript 3.6 版中的更新内容,包括:语言和编译器、新的 TypeScript Playground、编辑功能等。​


我们很高兴地宣布,TypeScript 3.6 正式面世了!


有些人可能还不太了解 TypeScript,这里做一个简单介绍:TypeScript 是一种基于 JavaScript 的语言,在后者的基础上添加了可选的静态类型;TypeScript 编译器可以检查这些类型以捕获程序中的常见错误(例如属性拼写错误和函数调用错误等);然后可以使用 TypeScript 编译器和 Babel 等工具将基于最前沿规范编写的 TypeScript 代码转换为符合标准的 ECMAScript 代码,后者可在任何浏览器或运行时(甚至是只支持 ES3 或 ES5 的旧版本)上运行。


TypeScript 不仅具备类型检查和较新的 ECMAScript 功能,其编辑工具也是业界一流水平,是 TypeScript 项目不可或缺的一部分;多种类型的编辑器为 TypeScript 提供了代码自动完成、重构和快速修复等功能。如果你在 Visual Studio 或 Visual Studio Code 中编辑过 JavaScript 文件,其实这些体验是由 TypeScript 提供的,所以你可能已经在不知情的情况下开始使用 TypeScript 了!


你可以查看TypeScript官方网站了解更多信息。TypeScript 可以通过NuGet获取,或在 npm 中键入以下命令:


npm install -g typescript
复制代码


可选的编辑器有:



不久的将来我们还会提供其他编辑器的支持


下面来看看 3.6 版中的更新内容吧!

语言和编译器

更严格的生成器

TypeScript 3.6 对迭代器和生成器函数的检查更严格了。在早期版本中,用户使用生成器时无法判断一个值是从生成器 yield 还是返回的。


function* foo() {    if (Math.random() < 0.5) yield 100;    return "Finished!"}
let iter = foo();let curr = iter.next();if (curr.done) { // TypeScript 3.5及之前版本把它当成 'string | number'. // 它应该知道这是 'string' ,因为 'done' 是 'true'! curr.value}
复制代码


此外,生成器之前会假定 yield 的类型总是 any。


function* bar() {    let x: { hello(): void } = yield;    x.hello();}
let iter = bar();iter.next();iter.next(123); // oops! runtime error!
复制代码


TypeScript 3.6 中的检查器现在知道第一段代码中的 curr.value 的正确类型应该是 string,并且在第二段代码中调用 next()时会正确地报错。这是因为 Iterator 和 IteratorResult 类型声明中现在引入了一些新的类型参数,且新版 TypeScript 会用 Generator 这个新类型来表示生成器。


Iterator 类型现在允许用户指定 yield 类型、返回的类型以及 next 可以接受的类型。


interface Iterator<T, TReturn = any, TNext = undefined> {    // 接收 0 或 1 参数 - 不接收 'undefined'    next(...args: [] | [TNext]): IteratorResult<T, TReturn>;    return?(value?: TReturn): IteratorResult<T, TReturn>;    throw?(e?: any): IteratorResult<T, TReturn>;}
复制代码


在此基础上,新的 Generator 类型是一个 Iterator,它总是同时存在 return 和 throw 方法,并且也是可迭代的。


interface Generator<T = unknown, TReturn = any, TNext = unknown>        extends Iterator<T, TReturn, TNext> {    next(...args: [] | [TNext]): IteratorResult<T, TReturn>;    return(value: TReturn): IteratorResult<T, TReturn>;    throw(e: any): IteratorResult<T, TReturn>;    <a href="">Symbol.iterator: Generator<T, TReturn, TNext>;}</a href="">
复制代码


为了区分返回值和生成值,TypeScript 3.6 将 IteratorResult 类型转换为差别联合类型:


type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>;
interface IteratorYieldResult<TYield> { done?: false; value: TYield;}
interface IteratorReturnResult<TReturn> { done: true; value: TReturn;}
复制代码


简而言之,这意味着你在直接处理迭代器时能够适当地缩小迭代器的值。


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


function* foo() {    let x: string = yield;    console.log(x.toUpperCase());}
let x = foo();x.next(); // 对 'next' 的第一个调用都会被忽略x.next(42); // error! 'number' 无法被分配给 'string'
复制代码


如果你更喜欢显式方法,那么还可以强制可以用 yield 表达式执行返回、yield 和计算的值的类型使用显式返回类型。下面的例子中,next( )只能用布尔值调用,并且根据 done 的值,value 可以是 string 或 number。


/** * - yields numbers * - returns strings * - can be passed in booleans */function* counter(): Generator<number, string, boolean> {    let i = 0;    while (true) {        if (yield i++) {            break;        }    }    return "done!";}
var iter = counter();var curr = iter.next()while (!curr.done) { console.log(curr.value); curr = iter.next(curr.value === 5)}console.log(curr.value.toUpperCase());
// prints://// 0// 1// 2// 3// 4// 5// DONE!
复制代码


这部分更改的详情可参阅github

更准确的数组扩展

在目标为 ES2015 之前的版本中,诸如 for/of 循环和数组扩展之类的结构用的发射有些复杂。因此 TypeScript 默认使用更简单的发射,只支持数组类型,并支持使用–downlevelIteration 标志在其他类型上迭代。在此标志下发出的代码更准确,但体积也大得多。


默认情况下–downlevelIteration 是关闭的,因为以 ES5 为目标的用户多数只使用带数组的迭代结构。但某些边缘情况下只支持数组的发射还是有一些可见的差异。


例如,以下示例


[...Array(5)]
复制代码


等同于下列数组:


[undefined, undefined, undefined, undefined, undefined]
复制代码


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


Array(5).slice();
复制代码


它们是有些不一样的。Array(5)生成一个长度为 5 的数组,但没有定义的属性槽!


1 in [undefined, undefined, undefined] // true1 in Array(3) // false
复制代码


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


这可能不太好理解,但其实有许多用户遇到了这种麻烦。TypeScript 3.6 不再使用 slice()和内置函数,而是引入了一个新的__spreadArrays助手,将 ECMAScript 2015 的内容在较旧的目标中模拟出来,不用 --downlevelIteration。 __spreadArrays 也可以在tslib中使用(如果你想缩小包的体积,那么非常值得一试)。


有关更多信息,请参阅资料

改进了 Promise 相关的用户体验

Promise 是当今最常用的异步数据方法之一。然而面向 Promise 的 API 通常会让用户感到困惑。TypeScript 3.6 引入了一些改进,避免用户错误处理 Promise。


例如,在将 Promise 的内容传递给另一个函数之前,人们往往会忘记.then()或 await 这部分内容。TypeScript 现在有了对应的错误消息,并告知用户他们可能应该使用 await 关键字。


interface User {    name: string;    age: number;    location: string;}
declare function getUserData(): Promise<User>;declare function displayUser(user: User): void;
async function f() { displayUser(getUserData());// ~~~~~~~~~~~~~// 类型 'Promise<User>' 的参数不能分配给类型 'User'的参数.// ...// Did you forget to use 'await'?}
复制代码


在 await 或.then()一个 Promise 之前就尝试访问方法也是很常见的错误。这类错误很多,我们都做了改进。


async function getCuteAnimals() {    fetch("https://reddit.com/r/aww.json")        .json()    //   ~~~~    // 属性 'json' 在类型 'Promise<Response>'上不存在.    //    // Did you forget to use 'await'?}
复制代码


这里的目的是就算用户没意识到要 await,起码这些消息能给出一些提示。


除了改进 Promise 相关的错误消息外,我们现在还在某些情况下提供了快速修复。



有关更多详细信息,请参阅原始问题及相关链接。

对标识符的 Unicode 支持改进

当发射到 ES2015 及更高版本的目标时,TypeScript 3.6 对标识符的 Unicode 字符提供了更好的支持。


const 𝓱𝓮𝓵𝓵𝓸 = "world"; // 以前不允许, 现在对 '--target es2015' 允许
复制代码

SystemJS 中的 import.meta 支持

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


// 这个模块:
console.log(import.meta.url)
// 被改成:
System.register([], function (exports, context) { return { setters: [], execute: function () { console.log(context.meta.url); } };});
复制代码

在环境上下文中允许 get 和 set 访问器

以前的 TypeScript 版本不允许在环境上下文中 get 和 set 访问器(例如在 declare-d 类中,或者在.d.ts 文件中)。理由是对于这些属性的读写而言访问器与属性没有区别;但是因为 ECMAScript 的类字段提案可能与现有 TypeScript 版本中的行为不同,我们意识到我们需要一种方法来对接这种行为差异,以便在子类中提供适当的错误。


因此,用户现在可以在 TypeScript 3.6 的环境上下文中编写 getter 和 setter。


declare class Foo {    // 在 3.6+ 版本中允许.    get x(): number;    set x(val: number): void;}
复制代码


在 TypeScript 3.7 中编译器也将利用此功能,以便生成的.d.ts 文件也发射 get/set 访问器。

环境类和函数可以合并

在以前版本的 TypeScript 中,任何情况下合并类和函数都是错误的。现在环境类和函数(具有 declare 修饰符或在.d.ts 文件中的类/函数)可以合并了。这意味着现在你可以编写以下代码:


export declare function Point2D(x: number, y: number): Point2D;export declare class Point2D {    x: number;    y: number;    constructor(x: number, y: number);}
复制代码


这样就用不着再写成:


export interface Point2D {    x: number;    y: number;}export declare var Point2D: {    (x: number, y: number): Point2D;    new (x: number, y: number): Point2D;}
复制代码


这样做的一个优点是可以很容易地表达可调用的构造函数模式,同时还允许名称空间与这些声明合并(因为 var 声明不能与 namespace 合并)。


在 TypeScript 3.7 中,编译器也将利用此功能,以便从.js 文件生成的.d.ts 文件可以正确捕获类函数的可调用性和可构造性。


更多详细信息请参阅 GitHub 上的原始PR

为–build 和–incremental 提供 API 支持

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 的实例。


有关这些 API 的详细信息可参阅资料

新的 TypeScript Playground

应用户呼吁,新版 TypeScript Playground 做了大幅改进,引入了许多全新功能。新版 Playground 基本上是社区流行的Artem TyurinTypeScript Playground的一个 fork。我们在这里非常感谢 Artem 提供的帮助!


新版 Playground 提供了许多新选项,包括:


  • target 选项(允许用户从 es5 切换到 es3、es2015、esnext 等)

  • 所有严格标志(包括 strict)

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


这些选项在共享 Playground 样本时也能使用,让用户可以更可靠地共享示例,无需告诉收件人“哦,别忘了打开 noImplicitAny 选项!”。


在不久的将来,我们将改进 Playground 样本功能、添加 JSX 支持、改进自动类型获取等,让用户使用 Playground 时如同在使用自己的编辑器一样。


我们欢迎大家在GitHub上提交反馈和请求!

编辑功能

分号感知代码编辑

Visual Studio 和 Visual Studio Code 等编辑器可以自动应用快速修复、重构、自动从其他模块导入值等转换。这些转换由 TypeScript 提供支持,而旧版本的 TypeScript 会无条件地在每个语句的末尾添加分号;但很多用户不喜欢这种风格,不希望编辑器自动插入分号。


TypeScript 现在变得非常聪明,可以在应用这些编辑时检测你的文件是否使用分号。如果你的文件不怎么用分号的话 TypeScript 也不会添加分号。


更多详细信息请参阅资料

更智能的自动导入

JavaScript 有许多不同的模块语法或约定:ECMAScript 标准是一种、Node 支持的一种(CommonJS)、AMD 一种、System.js 又是一种,还有更多!在大多数情况下 TypeScript 默认使用 ECMAScript 模块语法来自动导入,遇到有些使用不同编译器设置的 TypeScript 项目就不怎么合适,在使用纯 JavaScript 和 require 调用的 Node 项目中也不搭配。


TypeScript 3.6 变得更聪明了一些,可以先查看你现有的导入后再决定怎样自动导入其他模块。你可以在此处查看更多信息

重大更新

命名为“constructor”的类成员现在是构造函数

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


class C {    "constructor"() {        console.log("我是构造函数.");    }}
复制代码


注意有一个例外,就是计算属性的名称等于“constructor”的情况。


class D {    <a href="">"constructor" {        console.log("我不是一个构造函数 - 只是一个方法");    }}</a href="">
复制代码

DOM 更新

新版 lib.dom.d.ts 中的许多声明已被删除或更改。具体包括(但不限于)以下内容:


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

  • GlobalFetch 已经移除了,取而代之的是 WindowOrWorkerGlobalScope。

  • Navigator 上的某些非标准属性消失了。

  • experimental-webgl 上下文移除了。替代品是 webgl 或 webgl2。

JSDoc 注释不再合并

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


/** * @param {string} 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.}
复制代码

未来计划

想要了解官方团队未来要开展的工作,请查看今年 7 月至 12 月的半年路线图计划


我们希望这个新版本能继续改善你的开发体验。你有任何建议或遇到任何问题我们都很感兴趣,欢迎大家在GitHub上提交反馈。


英文原文:https://devblogs.microsoft.com/typescript/announcing-typescript-3-6/


2019-09-03 08:206119

评论

发布
暂无评论
发现更多内容

win版Microsoft Office 2016免激活专业增强版

iMac小白

Office 2016 下载 Office 2016激活版

低成本、高稳定性 | 满帮集团 Eureka 和 ZooKeeper 的上云实践

阿里巴巴云原生

阿里云 微服务 云原生 nacos

英特尔推进面向未来节点的技术创新,在2025年后巩固制程领先性

E科讯

win版IDimager Photo Supreme 2024(图片管理软件)激活版

iMac小白

老去在温暖的空间中,老去在智能的光芒里

脑极体

AI

VueScan Pro(专业扫描工具) v9.8.33 特别版下载

iMac小白

VueScan下载

win版Directory Opus(文件管理器) 专业版下载

iMac小白

Directory Opus下载 Directory Opus破解版 Directory Opus激活版

win版SketchUp Pro 2024 (草图大师2024)特别版下载

iMac小白

SketchUp2024下载 SketchUp2024激活版 SketchUp2024破解版

DevOps 进阶实践课,连续 4 期,看看有你想听的吗?

阿里云云效

阿里云 DevOps 云原生

前端面试题 - vue的双向绑定原理是什么?

Geek_fed966

组织架构图如何制作?用这个AI绘图软件一键生成!

彭宏豪95

人工智能 在线白板 AIGC 绘图软件 组织架构图

win版Windows System Control Center(WSCC)v7.0.9.1 注册版

iMac小白

谈谈 JVM 垃圾回收机制

快乐非自愿限量之名

JVM 虚拟机 垃圾回收

暗水印——空域:音频水印(看不见我吧 啦啦啦~)

京东科技开发者

Office Installer Plus(一键部署微软 Office) v1.15 特别版

iMac小白

win版VovSoft Batch URL Downloader(批量网址下载器)激活版

iMac小白

Python异常处理:基础到进阶的实用指南

我再BUG界嘎嘎乱杀

Python 编程语言 软件开发 异常处理

Flink的状态原语详述

木南曌

实时计算

软件测试学习笔记丨黑盒测试方法论-判定表

测试人

软件测试

win版Stardock Start11(Win11开始菜单工具) v2.08直装版

iMac小白

从内存泄露聊聊python内存管理

我再BUG界嘎嘎乱杀

Python 编程语言 内存管理 开发语言

DevOps 进阶实践课,连续 4 期,看看有你想听的吗?

阿里巴巴云原生

阿里云 DevOps 云原生

eBPF革命:定义网络虚拟化的第三阶段

品高云计算

科普:DO-178B

DevOps和数字孪生

航空航天 DO-178B

通过MVEL表达式和Apache Chain职责链模式解耦MQ消息处理节点的实践应用

京东科技开发者

win版WinCatalog 2024(磁盘管理)特别版

iMac小白

门保真度达99.9%,英特尔展示领先自旋量子比特器件性能

E科讯

TypeScript 3.6正式发布!新增4项突破性特点_语言 & 开发_Daniel Rosenwasser_InfoQ精选文章