TypeScript 4.6 正式发布,新功能一览

4,379

TypeScript 4.6 正式发布了!

如果想要使用TypeScript,可以通过NuGet下载,也可以使用npm命令来下载:npm install typescript

TypeScript 4.6的功能更新:

  • 支持super()前执行构造函数代码
  • --target es2022

自测试版和RC版以来有什么新功能?

TypeScript 4.6测试版本以来,有两个比较大的功能改进,分别是面向 Destructured Discriminated Unions(可辨识联合类型)控制流分析--target es2022,同时另一个值得注意的变化是在react-jsx 模式下删除了void 0 参数。

自RC版本发布之后,TypeScript 团队内部也做了重构,修复了一些问题,纠正了一些奇怪的错误信息,并将部分情况下的类型检查性能提高了3%。

支持super()前执行构造函数代码

在JavaScript类中,引用super() 之前,必须先调用this 。TypeScript也执行了这一点。在TypeScript中,如果一个构造函数的包含类有任何属性初始化器,那么在构造函数的开头包含任何代码都是错误的。

class Base {
    // ...
}

class Derived extends Base {
    someProperty = true;

    constructor() {
        // error!
        // have to call 'super()' first because it needs to initialize 'someProperty'.
        doSomeStuff();
        super();
    }
}

而现在 TypeScript 4.6在检查方面变得更加宽松,允许其他代码在super()...之前运行。

面向 Destructured Discriminated Unions(可辨识联合类型)控制流分析

TypeScript能够根据判别属性来缩小类型。例如,在下面的代码片段中,TypeScript能够通过检查kind 值来缩小action 的类型。

type Action =
    | { kind:  NumberContents , payload: number }
    | { kind:  StringContents , payload: string };

function processAction(action: Action) {
    if (action.kind ===  NumberContents ) {
        // `action.payload` is a number here.
        let num = action.payload * 2
        // ...
    }
    else if (action.kind ===  StringContents ) {
        // `action.payload` is a string here.
        const str = action.payload.trim();
        // ...
    }
}

这一特性使得持有不同数据的对象可以一起工作,不过需要制定一个共同字段来描述这些对象存在哪些数据。

如果想要取消上述例子中的kindpayload ,可以如下操作。

type Action =
    | { kind:  NumberContents , payload: number }
    | { kind:  StringContents , payload: string };

function processAction(action: Action) {
    const { kind, payload } = action;
    if (kind ===  NumberContents ) {
        let num = payload * 2
        // ...
    }
    else if (kind ===  StringContents ) {
        const str = payload.trim();
        // ...
    }
}

索引访问推理的改进

TypeScript现在可以正确地推断出索引访问类型,立即索引到一个映射的对象类型。

interface TypeMap {
     number : number;
     string : string;
     boolean : boolean;
}

type UnionRecord<P extends keyof TypeMap> = { [K in P]:
    {
        kind: K;
        v: TypeMap[K];
        f: (p: TypeMap[K]) => void;
    }
}[P];

function processRecord<K extends keyof TypeMap>(record: UnionRecord<K>) {
    record.f(record.v);
}

// This call used to have issues - now works!
processRecord({
    kind:  string ,
    v:  hello! ,

    // 'val' used to implicitly have the type 'string | number | boolean',
    // but now is correctly inferred to just 'string'.
    f: val => {
        console.log(val.toUpperCase());
    }
})

--target es2022

TypeScript 现在支持 --target es2022 。这意味着像类字段 (class fields) 这样的特性现在会有一个可以保留的稳定输出 target,也意味着新的内置功能可以使用新的--target 设置,或者使用--lib es2022

删除了react-jsx 中不必要的参数

以前,编译如下代码时--jsx react-jsx

export const el = 
foo
;

现在,TypeScript 将生成以下 JavaScript 代码:

import { jsx as _jsx } from  react/jsx-runtime ;
export const el = _jsx( div , { children:  foo  }, void 0);

在这种模式下,最后一个参数void 0是不必要的,删除它可以提高包的大小。

- export const el = _jsx( div , { children:  foo  }, void 0);
+ export const el = _jsx( div , { children:  foo  });