宣布打字稿3.9

2020-05-13 21:02:30

如果您不熟悉TypeScript,那么它是一种通过添加类型声明和注释的语法而构建在JavaScript之上的语言。TypeScript编译器可以使用此语法对代码进行类型检查,然后输出在许多不同运行时上运行的干净、可读的JavaScript。静态类型检查可以在我们运行代码之前,或者甚至在我们保存文件之前就告诉我们代码中的错误,这要归功于TypeScript丰富的跨编辑器编辑功能。但是,除了错误检查之外,在一些您最喜欢的编辑器中,TypeScript还支持诸如完成、快速修复和重构TypeScript和JavaScript之类的功能。事实上,如果您已经在使用Visual Studio或Visual Studio代码,那么在编写JavaScript代码时,您可能已经在使用TypeScript了!因此,如果您有兴趣了解更多信息,请访问我们的网站!

但是,如果您已经在项目中使用TypeScript,您可以通过NuGet获取它,也可以通过以下命令使用NPM:

对于这个版本,我们的团队一直专注于性能、改进和稳定性。我们一直致力于加速编译器和编辑体验,消除摩擦和剪纸,减少错误和崩溃。我们还从外部社区收到了许多有用且备受赞赏的功能和修复!

TypeScript的最新版本(大约3.7)更新了Promise.all和Promise.race等函数的声明。不幸的是,这引入了一些回归,特别是在混入带有NULL或未定义的值时。

接口Lion{roar():void}接口密封{singKissFromARose():void}异步函数visitZoo(lion Exhibit:Promise<;Lion>;,sealExhibit:Promise<;Seal|未定义>;){let[lion,seal]=等待Promise。all([lion Exhibit,sealExhibit]);狮子。Roar();//嗯哦//~//对象可能是';未定义';。}。

这是奇怪的行为!事实上,sealExhibit包含未定义的某种中毒类型的狮子,以包括未定义的。

多亏了Jack Bates的拉取请求,我们在TypeScript 3.9中的推理过程得到了改进,从而修复了这一问题。以上不再有错误。如果你因为承诺的问题而被困在老版本的打字稿上,我们鼓励你试试3.9!

如果您一直在关注我们的问题跟踪器和设计会议笔记,您可能知道围绕一个名为Waitted的新类型运算符所做的一些工作。此类型操作符的目标是在JavaScript中准确建模Promise展开的工作方式。

我们最初预计TypeScript3.9会发布,但由于我们已经使用现有的代码库运行了早期的TypeScript版本,我们意识到该功能需要更多的设计工作才能顺利地向所有人推出。因此,我们决定将该功能从我们的主要分支中删除,直到我们感觉更有信心为止。我们将对该功能进行更多的实验,但我们不会将其作为此版本的一部分发布。

打字本3.9出厂时有许多新的速度改进。在观察到Material-UI和Styled-Components等包的编辑/编译速度极低之后,我们的团队一直在关注性能。我们在这里深入研究了一系列不同的拉请求,这些请求优化了涉及大型联合、交集、条件类型和映射类型的某些病理情况。

每个Pull请求在某些代码库上的编译时间减少了大约5-10%。总而言之,我们相信我们已经将Material-UI样式项目的编译时间减少了大约25%。此外,我们还得到了微软团队的反馈,TypeScript3.9将他们的编译时间从26秒减少到了10秒左右。

我们还对编辑器场景中的文件重命名功能进行了一些更改。我们从Visual Studio代码团队那里听说,在重命名文件时,仅仅计算出需要更新哪些导入语句就可能需要5到10秒的时间。TypeScript 3.9通过更改编译器和语言服务如何缓存文件查找的内部结构来解决此问题。

虽然还有改进的空间,但我们希望这项工作能为每个人带来更快的体验!

假设我们正在用TypeScript编写一个库,并导出一些名为doStuff的函数作为公共API的一部分。该函数的类型声明它接受两个字符串,以便其他TypeScript用户可以得到类型检查错误,但它还执行运行时检查(可能仅在开发版本中),以向JavaScript用户提供有用的错误。

函数doStuff(abc:string,xyz:string){assert(typeof abc=";string";);assert(typeof xyz=";string";);//做一些事情}。

因此,当TypeScript用户误用该函数时,他们会得到一个有用的红色曲线和一条错误消息,而JavaScript用户会得到一个断言错误。我们想测试这个行为,所以我们将编写一个单元测试。

这就是TypeScript3.9带来新功能的原因://@ts-expect-error注释。当一行以//@ts-Expect-Error注释为前缀时,TypeScript将禁止报告该错误;但如果没有错误,TypeScript将报告//@ts-Expect-Error不是必需的。

我们非常感谢乔什·戈德伯格,他是实现这一功能的贡献者。有关更多信息,可以查看ts-Expect-Error拉取请求。

在某些方面,//@ts-expect-error可以充当隐藏注释,类似于//@ts-Ignore。不同之处在于,如果以下行没有错误,则//@ts-Ignore不会执行任何操作。

您可能想要将现有的//@ts-Ignore注释切换到//@ts-Expect-Error,并且您可能想知道哪种注释适合于将来的代码。虽然这完全取决于您和您的团队,但在某些情况下,我们有一些想法可供选择。

您编写的测试代码实际上希望类型系统在操作中出错。

您希望修复程序很快就会出现,而您只需要一个快速的解决方法。

您正处于一个规模合理的项目中,其中有一个主动团队,该团队希望在受影响的代码再次有效后立即删除抑制注释。

您有一个较大的项目,并且在没有明确所有者的代码中出现了新的错误

您正在进行两个不同版本的TypeScript之间的升级,在一个版本中有一行代码错误,但在另一个版本中没有一行代码错误。

老实说,你没有时间来决定这些选项中哪一个更好。

在TypeScript3.7中,我们引入了未调用函数检查,以便在忘记调用函数时报告错误。

函数hasImportantPermission():布尔值{//.}//哎呀!IF(HasImportantPermission){//~//此条件将始终返回TRUE,因为函数始终是定义的。//您的意思是要改为调用它吗?delete eAllTheImportantFiles();}。

但是,此错误仅适用于IF语句中的条件。多亏了Alexander Tarasyuk的拉取请求,该功能现在也在三元条件句中得到支持(即第二个?trueExpr:false seExpr语法)。

声明函数listFilesOfDirectory(dirPath:string):string[];声明函数isDirectory():boolean;函数getAllFiles(startFileName:string){const result:string[]=[];traverse(StartFileName);return result;函数遍历(currentPath:string){return isDirectory?//~/此条件将始终返回true//,因为函数始终已定义。//您的意思是要改为调用它吗?listFilesOfDirectory(CurrentPath)。forEach(遍历):result。Push(CurrentPath);}}。

TypeScript编译器不仅增强了大多数主要编辑器中的文本编辑体验,而且还增强了Visual Studio编辑器系列中的JavaScript体验以及更多功能。在编辑器中使用新的TypeScript/JavaScript功能会因编辑器的不同而有所不同,但是。

Visual Studio代码支持选择不同版本的TypeScript。或者,还有JavaScript/TypeScript Nighly扩展可以保持在最前沿(通常非常稳定)。

在较早的版本中,TypeScript总是假设不管您的文件是什么,您都想要一个ECMAScript样式的导入,如下所示。

然而,并不是每个人在编写JavaScript文件时都以ECMAScript样式的模块为目标。许多用户仍在使用CommonJS样式的Required(.)。这样的进口。

TypeScript现在可以自动检测您正在使用的导入类型,以保持文件样式的整洁和一致。

TypeScript的重构和快速修复通常不能很好地保存换行符。作为一个非常基本的示例,请看下面的代码。

const maxValue=100;/*start*/for(设i=0;i<;=maxValue;i++){//首先获取平方值。让Square=i**2;//现在打印平方的值。控制台。log(正方形);}/*结束*/。

如果我们在编辑器中突出显示从/*start*/到/*end*/的范围以提取到一个新函数,我们将得到如下所示的代码。

const maxValue=100;printSquares();函数printSquares(){for(设i=0;i<;=maxValue;i++){//首先获取平方值。让Square=i**2;//现在打印平方的值。控制台。log(正方形);}}。

这并不理想-我们在for循环中的每个语句之间都有一个空行,但是重构去掉了它!TypeScript3.9做了更多的工作来保存我们所写的内容。

const maxValue=100;printSquares();函数printSquares(){for(设i=0;i<;=maxValue;i++){//首先获取平方值。让Square=i**2;//现在打印平方的值。控制台。log(正方形);}}。

在某些情况下,我们可能忘记返回函数中最后一条语句的值,特别是在向箭头函数添加大括号时。

//在让F1=()=>;42之前//哎呀-不一样!设f2=()=>;{42}。

多亏了社区成员Wen lu Wang的拉请求,TypeScript可以提供快速修复,以添加缺少的返回语句、删除大括号,或者向看起来与对象文字可疑的箭头函数体添加圆括号。

编辑人员需要找出文件属于哪个配置文件,以便它可以应用适当的选项,并找出当前“项目”中还包括哪些其他文件。默认情况下,由TypeScript的语言服务器支持的编辑器通过遍历每个父目录来查找tsconfig.json。

其中一种情况是,当tsconfig.json只存在于引用其他tsconfig.json文件时。

//tsconfig.json{";files";:[],";References";:[{";path";:";./tsconfig.shared.json";},{";path";:";./tsconfig.front tend.json";},{";path";:";./tsconfig.backend.json&。}、]}。

这个除了管理其他项目文件什么都不做的文件在某些环境中通常被称为“解决方案”。在这里,这些tsconfig.*.json文件都不会被服务器拾取,但是我们确实希望语言服务器理解,当前的.ts文件可能属于根tsconfig.json中提到的项目之一。

TypeScript 3.9添加了对此配置的编辑方案的支持。有关更多详细信息,请查看添加此功能的Pull请求。

TypeScript最近实现了可选链接运算符,但我们收到了用户反馈,可选链的行为(?.)。使用非空断言运算符(!)。是非常违反直觉的。

在上面的代码中,圆括号停止了可选链接的“短路”行为,因此如果没有定义foo,访问baz将导致运行时错误。

指出这一行为的巴别塔团队以及向我们提供反馈的大多数用户都认为这种行为是错误的。我们也是!我们听到最多的是!操作符应该“消失”,因为其目的是从栏的类型中删除NULL和未定义的内容。

这是一个突破性的变化,但我们相信大多数代码在编写时都考虑到了新的解释。想要恢复到旧行为的用户可以在!的左侧添加显式括号。接线员。

JSX规范禁止在文本位置使用}和>;字符。TypeScript和Babel都决定执行这一规则,以使其更符合要求。插入这些字符的新方法是使用HTML转义代码(例如<;div>;2&;gt;1<;/div>;)或插入带有字符串文字的表达式(例如<;div>;2{";>;";}1<;/div>;)。

幸运的是,由于Brad Zacher发出的强制执行此操作的Pull请求,您将收到类似以下内容的错误消息。

意外令牌。您说的是`{';>;&39;}`还是`&;gt;`?意想不到的令牌。你说的是``还是`&;rbrace;`?

让Directions=<;div>;导航到:菜单栏>;工具>;选项<;/div>;//~~//意外标记。您是指`{';&>;}`还是`&;>`?

该错误消息提供了一个方便的快速修复,多亏了Alexander Tarasyuk,如果您有很多错误,您可以批量应用这些更改。

通常,如果A或B可以指定给C,则像A&A;B这样的交叉点类型可以指定给C;但是,有时可选特性会出现问题。例如,请执行以下操作:

接口A{a:number;//注意这是';number';}接口B{b:string;}接口C{a?:Boolean;//注意这是';Boolean';b:String;}声明let x:A&;B;声明let y:c;y=x;

在以前的TypeScript版本中,这是允许的,因为A与C完全不兼容,而B与C兼容。

在TypeScript3.9中,只要交叉点中的每个类型都是具体的对象类型,类型系统就会一次性考虑所有属性。因此,TypeScript将看到A&A;B的a属性与C的a属性不兼容:

类型';A&;B';不可分配给类型';C';。属性类型';a';不兼容。类型';编号';不可分配给类型';布尔|未定义';。

在少数情况下,您可能最终得到的类型描述的值根本不存在。例如

声明函数smushObjects<;T,U>;(x:t,y:u):T&;U;接口Circle{Kind:";Circle";;Radius:Number;}接口Square{Kind:";Square";;side Length:Number;}声明let x:Circle;声明let y:Square;let z=smushObjects(x,y);console。log(z.。种类);

这段代码有点奇怪,因为实际上无法创建Circle和Square的交集-它们有两个不兼容的种类字段。在以前版本的TypeScript中,此代码是允许的,并且种类本身的类型永远不会被允许,因为";Circle&34;&;Square&34;描述了一组永远不可能存在的值。

在TypeScript3.9中,这里的类型系统更为激进-它注意到由于Circle和Square的种类属性,它们不可能相交。因此,它不是将z.Kind类型折叠为Never,而是将z类型本身(Circle&Amp;Square)折叠为Never。这意味着上面的代码现在错误为:

我们观察到的大多数中断似乎与稍微不正确的类型声明相对应。更多详情请参见原始拉流请求。

在旧版本的TypeScript中,类中的get和set访问器是以使其可枚举的方式发出的;然而,这不符合ECMAScript规范,该规范规定它们必须是不可枚举的。因此,针对ES5和ES2015的TypeScript代码的行为可能不同。

多亏了GitHub用户路径的拉取请求,TypeScript3.9现在在这方面与ECMAScript更加一致。

在早期版本的TypeScript中,约束为ANY的类型参数可以被视为ANY。

这是一个疏忽,所以TypeScript3.9采取了一种更保守的方法,并对这些有问题的操作发出了一个错误。

函数foo<;T扩展任何>;(arg:t){arg.。类型';T';上不存在spfjgerijghoed;//~//属性';spfjgerijghoed';。}。

在以前的打字脚本版本中,如果foo没有导出任何值,那么像export*from";foo&34;这样的声明就会被删除到我们的JavaScript输出中。这种发射是有问题的,因为它是类型定向的,不能被Babel模仿。TypeScript 3.9将始终发出这些导出*声明。在实践中,我们预计这不会破坏太多现有代码,但是绑定器可能更难摇动代码。

当面向模块系统(如ES5及更高版本中的CommonJS)时,TypeScript将使用GET访问器来模拟活动绑定,以便在任何导出模块中都能看到对一个模块中变量的更改。此更改旨在使TypeScript的发出更符合ECMAScript模块。

TypeScript现在将在ES5和更高版本中针对模块系统(如CommonJS)时将导出的声明提升到文件顶部。此更改旨在使TypeScript的发出更符合ECMAScript模块。例如,代码如下所示。

但是,由于导出现在使用Get-Accessors,此赋值将抛出,因为__exportStar现在生成不能用简单赋值覆盖的Get-Accessors。相反,TypeScript 3.9发出以下内容:

我们希望TypeScript3.9能让您的日常编码变得有趣、快速,并且总体来说是一种使用的乐趣。要了解我们的下一个版本,您可以跟踪4.0迭代计划和我们的特性路线图。