TypeScript 4.6 有什么新功能?

x33g5p2x  于2022-03-21 转载在 其他  
字(3.4k)|赞(0)|评价(0)|浏览(356)

TypeScript 4.6 是今年针对静态类型 JavaScript 超集的第一个功能版本。它围绕构造函数、编译和代码分析添加了多项改进。在升级之前,还需要注意一些重大更改。

控制流分析改进

此版本为 TypeScript 的控制流分析功能带来了多项增强功能。它们更好地使 TypeScript 能够更准确地理解代码的运行方式,从而实现更窄的类型定义和更少的意外错误。

第一个变化涉及已从对象解构的判别属性联合。它适用于您使用由多个对象组成的联合类型的情况。联合中的各个对象可能在其类型定义上有所不同,但仍共享一些键。

通常使用这些共享密钥有条件地检查数据结构的其他部分。使用带有解构分配的此工作流时,TypeScript 过去常常出错。解构语法创建了全新的变量,没有将它们链接为对象属性的关联。编译器现在记住这些值来自同一个对象,从而可以编写更简单的代码。

发布公告使用与此类似的示例:

type Action =
    | {kind: "Number", data: number}
    | {kind: "String", data: string};
 
function handle(action: Action) {
 
    const {kind, data} = action;
 
    if (kind === "Number") {
        const square = (data * data);
    }
    else if (kind === "String") {
        const lines = data.split("\n");
    }
 
}

TypeScript 4.5 不允许此代码。解构赋值 ( const {kind, data}) 创建了两个独立变量;编译器无法理解kind存在Number方式data必须是一种number类型。现在它将认识到这一事实,让您可以将解构语法与可区分的联合一起使用。

控制流分析也围绕相关参数进行了加强。此语法允许您为可变参数的性质指定复杂的规则。这是使用此行为的函数的类型定义:

type Func = (...args: ["Number", number], ["String", string]) => void;

此函数的签名指定您可以传递String或Number作为其第一个参数。如果使用Number,下一个参数必须是类型的值number。或者,string如果它在后面,则可以给出a String。

与上面的区分联合示例类似,TypeScript 现在根据它们之前的值缩小依赖参数的类型:

const demo: Func = (kind, data) => {
    if (kind === "Number") {
        const square = (data * data);
    }
    else if (kind === "String") {
        const lines = data.split("\n");
    }
};

编译器现在意识到data必须是numberif kindis Number。此代码会在 TypeScript 4.5 中引发错误。

构造函数增强

扩展父类的 JavaScript 类的构造函数必须在使用关键字super()之前调用:this

// Not allowed - "this" used before "super"
class B extends A {
    constructor() {
        this.demo = "foobar";
        super();
    }
}
 
// Working correct order
class C extends A {
    constructor() {
        super();
        this.demo = "foobar";
    }
}

TypeScript 历来在执行此要求方面过于严格。如果包含属性初始值设定项的类在语句之前有任何代码super(),即使它从未引用过,它们也会被拒绝this:

const example = () => null;
 
class C extends A {
 
    demoProperty = true;
 
    // Unnecessarily treated as invalid 
    constructor() {
        example();
        super();
    }
}

这种处理有助于优化 TypeScript 对this之前使用的真实实例的检查super()。它还导致许多可接受的代码无法编译,迫使作者重构实际上是有效 JavaScript 的工作。

TypeScript 4.6 解决了这个问题。编译器现在与 vanilla JavaScript 保持一致,super()如果它不会导致this被使用,则允许之前的代码。这使您可以更自由地以对每种情况最有意义的方式编写类构造函数。TypeScript 仍然会检测到任何this过早引用的真实案例。

更多推理改进

索引访问推断现在更加精确。这使编译器可以看到索引到映射对象的索引访问类型。虽然这在以前已经成为可能,但较旧的 TypeScript 版本产生的推理质量很差,并不总是完全了解映射对象的类型。

TypeScript 的递归深度检查也进行了调整,以更好地检测不兼容的递归类型。此更改可以提高类型检查的性能,因为它有助于在类型的递归开始无限扩展时提前退出。改进的重点是如何将递归应用于使用泛型的类型。

ES2022 目标

该–target标志已获得支持es2022作为一个值。它可以充分利用 ES2022 功能,确保在您的稳定版本中保留类字段和属性等语法,而无需进行转译。Error.cause

–target es2022您可以通过将标志传递给 ES2022 来定位tsc. 或者,在您的项目文件中更改compilerOptions.target为:es2022tsconfig.json

{
    "compilerOptions": {
        "target": "es2022"
    }
}

更多 JavaScript 语法和绑定错误

TypeScript 现在会显示更多标准的 JavaScript 语法和绑定错误。这些错误将在编译过程中出现,并且当您在编辑器中打开带有适用于 Visual Studio、Visual Studio Code 或 Sublime Text 的 TypeScript 扩展的文件时。

重复const语句、不正确使用关键字和范围错误现在将由 TypeScript 显示,在您工作时为您提供即时反馈。// @ts-nocheck可以通过在源文件顶部添加注释来禁用该功能。

此添加构成了一项重大更改,因为源文件现在必须包含语法正确的 JavaScript。TypeScript 的编译器以前忽略了大多数类型的 JavaScript 语法错误。如果您认为您的代码库与此强制措施不兼容,您应该使用注释关闭该功能。

另一个重大变化

此更新中有第二个重大更改:对象休息表达式现在从通用对象中删除不可传播的成员。这提高了与非泛型类型解构的一致性,但意味着您现有的变量可能缺少它们在 TypeScript 4.5 中拥有的一些属性。

具有不可扩展值的属性(例如标量和函数)将从其余表达式中省略。这也适用于其他不可传播的情况,例如类实例的非公共成员和this. 像下面这样的代码曾经可以工作,但现在会抛出错误:

class Demo {
 
    prop = "example";
 
    sayHello() {
        console.log("Hello World");
    }
 
    methodWithRest() {
 
        const {prop, ...rest} = this;
 
        // ERROR - Non-spreadable value (function) will be dropped
        rest.sayHello();
 
    }
 
}

概括

TypeScript 4.6 增强了类型推断,改进了子类构造函数的处理,并将 ES2022 添加为支持的输出目标。在扩展的 JavaScript 语法错误检测和删除不可扩展的对象休息表达式成员的形式中,还有一些狭窄的突破性变化。npm update typescript您可以通过运行或npm install typescript@latest在项目的工作目录中升级到新版本。

该更新还标志着用于分析 TypeScript 现有类型生成跟踪的高级新工具的首次亮相。跟踪分析器使用来自的输出tsc --generateTrace来帮助您查明复杂的类型表达式是如何降低编译器的速度的。

相关文章