【资讯】微软宣布 TypeScript 4.8 正式发布

简介: 就在上周微软发布了 TypeScript 4.8 新版本,一起来看看都有哪些新的功能。

就在上周微软发布了 TypeScript 4.8 新版本,一起来看看都有哪些新的功能:

如果您还不熟悉 TypeScript,可以在 官网了解有关 TypeScript 的更多信息。它是一种基于 JavaScript 并为类型添加语法的语言。这些类型让您可以将您的期望和假设放入代码中,然后可以通过 TypeScript 类型检查器检查这些假设。

这种检查可以帮助避免拼写错误调用未初始化的值混淆函数的参数等等。类型不仅仅是检查,它还用于为您提供强大的 TypeScript 和 JavaScript 编辑体验,支持代码完成、转到定义、重命名等。我们所熟悉的 Visual Studio 就是完全使用 TypeScript 开发的!

要开始使用 TypeScript,可以通过 NuGet获取它,或者通过以下命令使用 npm:

npm install -D typescript

还可以通过以下方式获得编辑器支持

自 Beta 版和 RC 版以来有什么新变化?

测试版发布 以来,其稳定版现在支持排除哪些文件被考虑在自动导入中。测试版发布帖子也没有记录类型签名中未使用的解构别名的突破。此外,Beta 版和 RC 帖子都没有记录关于在 TypeScript 语法树上放置装饰器的 API 中断。这些中断现在在正确性修复和重大更改部分中进行了详细说明

改进交叉类型、联合兼容性和收窄

TypeScript 4.8 版本对 --strictNullChecks 进行了改进增强,这些更改会联合类型与交叉类型的工作方式,并在类型收缩时加以利用。

例如,人们普遍认为 unknown 和 {} | null | undefined 很接近,因为它接受nullundefined 和任何其他类型。TypeScript 现在可以识别这一点,并允许从to赋值。

function f(x: unknown, y: {} | null | undefined) {
    x = y; // always worked
    y = x; // used to error, now works
}

另一个变化是,{} 与任何其他对象类型相交会直接简化为该对象类型。这意味着能够像下面这样重写 NonNullable ,因为 {} & null 和 {} & undefined 只是被扔掉了。

- type NonNullable<T> = T extends null | undefined ? never : T;
+ type NonNullable<T> = T & {};

这个改进可以减少和分配像这样的交集类型,而条件类型目前不能。

function foo<T>(x: NonNullable<T>, y: NonNullable<NonNullable<T>>) {
    x = y; // always worked
    y = x; // used to error, now works
}

这些更改还使我们能够在控制流分析和类型缩小方面进行明智的改进。

function narrowUnknownishUnion(x: {} | null | undefined) {
    if (x) {
        x;  // {}
    }
    else {
        x;  // {} | null | undefined
    }
}

function narrowUnknown(x: unknown) {
    if (x) {
        x;  // used to be 'unknown', now '{}'
    }
    else {
        x;  // unknown
    }
}

我们现在可以在没有任何类型断言的情况下定义以下函数。

function throwIfNullable<T>(value: T): NonNullable<T> {
    if (value === undefined || value === null) {
        throw Error("Nullable value!");
    }

    // Used to fail because 'T' was not assignable to 'NonNullable<T>'.
    // Now narrows to 'T & {}' and succeeds because that's just 'NonNullable<T>'.
    return value;
}

有关这些改进的更多细节,可以在此处阅读更多信息

改进了对infer模板字符串类型中的类型的推理

TypeScript 最近引入了一种向条件类型中的类型变量添加extends约束的方法。infer

// Grabs the first element of a tuple if it's assignable to 'number',
// and returns 'never' if it can't find one.
type TryGetNumberIfFirst<T> =
    T extends [infer U extends number, ...unknown[]] ? U : never;

如果这些infer类型出现在模板字符串类型中并且被限制为原始类型,TypeScript 现在将尝试解析出文字类型。

// SomeNum used to be 'number'; now it's '100'.
type SomeNum = "100" extends `${infer U extends number}` ? U : never;

// SomeBigInt used to be 'bigint'; now it's '100n'.
type SomeBigInt = "100" extends `${infer U extends bigint}` ? U : never;

// SomeBool used to be 'boolean'; now it's 'true'.
type SomeBool = "true" extends `${infer U extends boolean}` ? U : never;

这现在可以更好地传达库在运行时将做什么,并提供更精确的类型。

可以在此处查看有关此功能的更多信息

--build--watch--incremental 性能改进

TypeScript 4.8 引入了一些优化,这些优化现在能够避免在模式的无操作更改期间花费时间更新时间戳,这使得重建速度更快,并避免与可能正在监视 TypeScript 输出的其他构建工具混淆。

微软生成在一个相当大的内部代码库中,他们已经看到许多简单的常见操作的时间减少了 10%-25%,在无变化的情况下减少了大约 40% 的时间,而在 TypeScript 代码库上也看到了类似的结果。

可以在 GitHub 上查看更改以及性能结果

比较对象和数组文字时的错误

在 JavaScript 中,通常 ===== 只能在对象(以及数组)之间检查两个引用是否指向相同的值,并不能判断值相等,团队认为这有可能导致生产代码中的一些错误。TypeScript 现在不允许像下面这样的代码。

if (peopleAtHome === []) {
//  ~~~~~~~~~~~~~~~~~~~
// This condition will always return 'false' since JavaScript compares objects by reference, not value.
    console.log("here's where I lie, broken inside. </3")
    adoptAnimals();
}

可以在此处查看所涉及的更改

从绑定模式改进推导

在某些情况下,TypeScript 会从绑定模式中选择一个类型以进行更好的推导。

declare function chooseRandomly<T>(x: T, y: T): T;

let [a, b, c] = chooseRandomly([42, true, "hi!"], [0, false, "bye!"]);
//   ^  ^  ^
//   |  |  |
//   |  |  string
//   |  |
//   |  boolean
//   |
//   number

了解更多信息,可以查看 GitHub 上的更改。

文件监视修复(尤其是跨 git checkout

TypeScript 在 watch 模式和编辑器场景下很难对某些文件进行修改,有时症状是陈旧的或不准确的错误,可能需要重新启动 tsc 或 VS Code。如果在Unix系统中使用vim保存文件或在git中交换分支的话,这种情况经常发生。

这是由于对 Node.js 如何跨文件系统处理重命名事件的假设造成的。Linux 和 macOS 使用的文件系统使用inode,并且Node.js 会将文件观察程序附加到 inode 而不是文件路径。因此,当 Node.js 返回一个观察者对象时,它是正在观察路径还是在索引节点,得取决于平台和文件系统。

如果 TypeScript 检测到磁盘上仍然存在路径,它会尝试重用相同的观察者对象,这是为了提高效率,但也就是它导致了问题所在,因为即使该路径上仍然存在一个文件,也可能已经创建了一个不同的文件,并且该文件将具有不同的 inode。因此,TypeScript 最终会重用 watcher 对象,而不是在原始位置安装新的 watcher,并在可能完全不相关的文件中监视更改。因此 TypeScript 4.8 现在可以在 inode 系统上处理这些情况,并正确安装新的观察程序并修复此问题。

可以在此处查看有关文件监视的特定修复

Find-All-References 性能改进

在编辑器中运行 find-all-references 时,TypeScript 现在能够更智能地聚合引用。这将 TypeScript 在其自己的代码库中搜索广泛使用的标识符所花费的时间减少了约 20%。

可以在此处阅读有关改进的更多信息

从自动导入中排除特定文件

TypeScript 4.8引入了一个编辑器偏好,用于从自动导入中排除文件。在Visual Studio Code中,文件名或glob可以添加在Settings UI中的“自动导入文件排除模式”下,或者在.vscode/ Settings中。json文件:

{
    // Note that `javascript.preferences.autoImportFileExcludePatterns` can be specified for JavaScript too.
    "typescript.preferences.autoImportFileExcludePatterns": [
      "**/node_modules/@types/node"
    ]
}

这在无法避免编译中包含某些模块或库,但又不太希望它们导入的情况下很有用。这些模块可能有很多可能会污染自动导入列表并使其更难自动的导出,而此选项可以在这些情况下提供帮助。

您可以在此处查看有关实施的更多细节

正确性修复和重大更改

由于类型系统更改的性质,可以进行的更改很少不会影响某些代码;但是,有一些更改更有可能需要调整现有代码。

lib.d.ts更新

虽然TypeScript努力避免大的中断,但即使是对内置库的小改动也会导致问题。我们不认为DOM和lib.d.ts更新会导致重大中断,但一个值得注意的变化是Errors上的cause属性现在的类型为unknown,而不是Error。

不受约束的泛型不再可分配给{}

在 TypeScript 4.8 中,对于启用了 strictNullChecks 的项目,当不受约束的类型参数被用在 null 或 undefined 不是合法值的位置时,TypeScript现在会正确地发出错误。这将包括任何需要 {}object 或具有所有可选属性的对象类型。

一个简单的例子:

// Accepts any non-null non-undefined value
function bar(value: {}) {
  Object.keys(value); // This call throws on null/undefined at runtime.
}

// Unconstrained type parameter T...
function foo<T>(x: T) {
    bar(x); // Used to be allowed, now is an error in 4.8.
    //  ~
    // error: Argument of type 'T' is not assignable to parameter of type '{}'.
}

foo(undefined);

如上所示,这样的代码有一个潜在的错误 null undefined 这些值可以通过这些不受约束的类型参数间接传递给不应该观察这些值的代码。

此行为也将在类型位置中可见,一个例子是:

interface Foo<T> {
  x: Bar<T>;
}

interface Bar<T extends {}> { }

不想处理的现有代码null可以undefined通过传播适当的约束来修复。

- function foo<T>(x: T) {
+ function foo<T extends {}>(x: T) {

另一种解决方法是在运行时检查nullundefined

  function foo<T>(x: T) {
+     if (x !== null && x !== undefined) {
          bar(x);
+     }
  }

如果知道由于某种原因,通用值不能是nullor undefined,可以只使用非空断言。

  function foo<T>(x: T) {
-     bar(x);
+     bar(x!);
  }

有关更多信息,可以查看引入此内容的更改以及关于无约束泛型现在如何工作的具体讨论问题

装饰器放置在modifiersTypeScript 的语法树上

TypeScript 公开了一个名为 ModifierLike 的新类型别名,它是一个 Modifier 或 Decorator。

export type ModifierLike = Modifier | Decorator;

有关更多信息,请参阅周围的更改

无法在 JavaScript 文件中导入/导出类型

TypeScript 以前允许 JavaScript 文件在 import 和 export 语句中导入和导出使用类型声明但没有值的实体,这种行为是不正确的,因为在 ECMAScript 模块下,不存在的值的命名导入和导出将导致运行时错误。当一个 JavaScript 文件在 ——checkJs 下或通过 // @ts-check 注释进行类型检查时,TypeScript现在会发出一个错误。

// @ts-check

// Will fail at runtime because 'SomeType' is not a value.
import { someValue, SomeType } from "some-module";

/**
 * @type {SomeType}
 */
export const myValue = someValue;

/**
 * @typedef {string | number} MyType
 */

// Will fail at runtime because 'MyType' is not a value.
export { MyType as MyExportedType };

要从另一个模块引用类型,可以直接限制导入。

- import { someValue, SomeType } from "some-module";
+ import { someValue } from "some-module";
  
  /**
-  * @type {SomeType}
+  * @type {import("some-module").SomeType}
   */
  export const myValue = someValue;

要导出类型,只需/** @typedef */在 JSDoc 中使用注释即可。 @typedef注释已经自动从其包含的模块中导出类型。

  /**
   * @typedef {string | number} MyType
   */

+ /**
+  * @typedef {MyType} MyExportedType
+  */
- export { MyType as MyExportedType };

可以在此处阅读有关更改的更多信息

绑定模式中未使用的重命名现在是类型签名中的错误

TypeScript 的类型注释语法通常看起来可以在解构值时使用。例如,采用以下函数。

declare function makePerson({ name: string, age: number }): Person;

读到这个签名时,您可能会认为 makePerson 显然接受了一个对象,该对象的 name 属性为类型字符串,age 属性为类型数字。然而 makePerson 虽然确实表示它将接受一个具有名称和年龄属性的对象,却没有为它们指定类型,它只是说它将名称和年龄分别重命名为字符串和数字。

在纯类型构造中,编写这样的代码是没有用的,而且通常是错误的,因为开发人员通常认为他们正在编写类型注释。

TypeScript 4.8 使这些成为错误,除非稍后在签名中引用它们。编写上述签名的正确方法如下:

declare function makePerson(options: { name: string, age: number }): Person;
// or
declare function makePerson({ name, age }: { name: string, age: number }): Person;

在此处阅读更改

下一步是什么?

TypeScript 目前正在开发 4.9 版。如果想了解具体时间表和该版本的计划功能,可以查看TypeScript 4.9 迭代计划

最后,希望 TypeScript 团队能实现让编码变得快乐的愿景吧~

相关文章
|
JavaScript 前端开发 编译器
开发者热议:微软新提议或将“彻底”改变 JavaScript 和 TypeScript!
开发者热议:微软新提议或将“彻底”改变 JavaScript 和 TypeScript!
167 0
开发者热议:微软新提议或将“彻底”改变 JavaScript 和 TypeScript!
|
JavaScript 前端开发 安全
微软开源 TypeScript 编绎器
TypeScript 是可规模扩展的JavaScript语言。TypeScript为JavaScript增加了可选类型,类和模块(classes and modules)。TypeScript支持任何浏览器的大型JavaScript应用程序。在任何主机和任何操作系统上,TypeScript 都是被支持的。TypeScript 编译成的是可读的、基于标准的 JavaScript。您可以尝试一下在一些平台上通过我们的博客和 Twitter 账户跟上最新的动态。
184 0
|
JavaScript C++ 前端开发
|
Web App开发 JavaScript 前端开发
微软新推TypeScript取代JavaScript
微软新推TypeScript取代JavaScript TypeScript是一个应用程序级的JavaScript开发语言。 TypeScript是JavaScript的超集,可以编译成纯JavaScript。
674 0
|
Web App开发 JavaScript 前端开发
微软新推TypeScript取代JavaScript
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 https://blog.csdn.net/chszs/article/details/8036529 微软新推TypeScript取代JavaScript TypeScript是一个应用程序级的JavaScript开发语言。
757 0
|
2月前
|
JavaScript 前端开发 安全
深入理解TypeScript:增强JavaScript的类型安全性
【10月更文挑战第8天】深入理解TypeScript:增强JavaScript的类型安全性
63 0
|
2月前
|
JavaScript 前端开发 开发者
深入理解TypeScript:类型系统与实用技巧
【10月更文挑战第8天】深入理解TypeScript:类型系统与实用技巧
|
3月前
|
存储 JavaScript
typeScript进阶(11)_元组类型
本文介绍了TypeScript中的元组(Tuple)类型,它是一种特殊的数组类型,可以存储不同类型的元素。文章通过示例展示了如何声明元组类型以及如何给元组赋值。元组类型在定义时需要指定数组中每一项的类型,且在赋值时必须满足这些类型约束。此外,还探讨了如何给元组类型添加额外的元素,这些元素必须符合元组类型中定义的类型联合。
52 0
|
27天前
|
设计模式 JavaScript 安全
TypeScript性能优化及代码质量提升的重要性、方法与策略,包括合理使用类型注解、减少类型断言、优化模块导入导出、遵循编码规范、加强代码注释等
本文深入探讨了TypeScript性能优化及代码质量提升的重要性、方法与策略,包括合理使用类型注解、减少类型断言、优化模块导入导出、遵循编码规范、加强代码注释等,旨在帮助开发者在保证代码质量的同时,实现高效的性能优化,提升用户体验和项目稳定性。
42 6
|
26天前
|
开发框架 JavaScript 前端开发
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势
TypeScript 是一种静态类型的编程语言,它扩展了 JavaScript,为 Web 开发带来了强大的类型系统、组件化开发支持、与主流框架的无缝集成、大型项目管理能力和提升开发体验等多方面优势。通过明确的类型定义,TypeScript 能够在编码阶段发现潜在错误,提高代码质量;支持组件的清晰定义与复用,增强代码的可维护性;与 React、Vue 等框架结合,提供更佳的开发体验;适用于大型项目,优化代码结构和性能。随着 Web 技术的发展,TypeScript 的应用前景广阔,将继续引领 Web 开发的新趋势。
35 2
下一篇
DataWorks