Typescript新特性 [4.3 ~ 5.2]
Typescript一直保持着3个月一个release,从2021年5月至今发布了10个版本(5.2将在8月release)。 本文盘点各个版本中的主要更新,着重在语言特性,其他有关性能等其他方面的更新请自行查看路线图。
4.3
分离的setter类型
允许getter和setter指定不同的类型。
下例中,size
是一个数字,但是同时setter可以接受字符串并转换。
4.3版本中依然限制getter返回类型必须可转换为setter入参类型。这一限制在5.1版本中进一步宽松,允许getter与setter的类型完全无关,Unrelated types for getters and setters
class Thing {
#size = 0;
get size(): number {
return this.#size;
}
set size(value: string | number | boolean) {
let num = Number(value);
if (!Number.isFinite(num)) {
this.#size = 0;
return;
}
this.#size = num;
}
}
const thing = new Thing();
thing.size = '123';
console.log(thing.size); // 123
thing.size = 'abc';
console.log(thing.size); // 0
#private私有元素
允许使用#
前缀定义类的私有元素,满足了ECMA标准。
相比于private
关键字,#privte
元素在运行时也是私有的,更为安全。
class Foo {
#someField = 0;
#someMethod() {
}
}
override关键字
- 新增
override
关键字,标识一个方法覆盖了父类方法。 - 并可以通过
--noImplicitOverride
flag来禁止隐式的覆盖。
class SomeComponent {
show() {
}
hide() {
}
}
class SpecializedComponent extends SomeComponent {
override show() {
}
// ts error
hide() {
}
}
其他
4.4
控制流中的类型分析
Typescript可以进行更加复杂且精准的类型判断,使得控制流中的(主要是if-else)类型更加精确。
由于涉及的情况多种多样,请自行查看官方实例。
static block
类中允许定义静态代码块。
// Prints:
// 1
// 2
// 3
class Foo {
static prop = 1
static {
console.log(Foo.prop++);
}
static {
console.log(Foo.prop++);
}
static {
console.log(Foo.prop++);
}
}
其他
- symbol和模板字符串可以作为索引签名,即
[key: symbol]: string
。Doc - 新增
--useUnknownInCatchVariables
flag,使得catch类型默认为unknown(原本是any)。Doc
4.5
Awaited工具类
新增工具类Awaited
用于递归地得到最终的Promise泛型。
// A = string
type A = Awaited<Promise<string>>;
// B = number
type B = Awaited<Promise<Promise<number>>>;
// C = boolean | number
type C = Awaited<boolean | Promise<number>>;
其他
export interface Success {
type: `${string}Success`;
body: string;
}
export interface Error {
type: `${string}Error`;
message: string
}
export function handler(r: Success | Error) {
if (r.type === "HttpSuccess") {
const token = r.body; // r is Success
}
}
4.6
4.7
Typescript 4.7主要改动是针对ESM和CJS的兼容性问题。
4.8
允许infer进行extend约束
现在infer类型内可以进行extend约束(仅基本类型),使得推导类型进行类型转换。
type SomeNum = "100" extends `${infer U extends number}` ? U : never;
type SomeBool = "true" extends `${infer U extends boolean}` ? U : never;
4.9
satisfied关键字
新增satisified
关键字,可以看作是只做约束而不作转换的as
操作。
这一操作对于定义常量(一般是映射用)非常有用。
具体示例参见官方文档
in缩小类型
in
关键字现在会合并检查的key以缩小类型,见下例。
interface Context {
packageJSON: unknown;
}
function tryGetPackageName(context: Context): string | undefined {
const packageJSON = context.packageJSON;
// Check to see if we have an object.
if (packageJSON && typeof packageJSON === "object") {
// Check to see if it has a string name property.
if ("name" in packageJSON && typeof packageJSON.name === "string") {
// Not work before 4.9
return packageJSON.name;
}
}
return undefined;
}
其他
5.0
Decorator
Typescript 5.0是一个非常大的版本更新,主要包括了Decorator装饰器。
装饰器还未正式纳入ECMA,现在正处在Stage 3。ECMA Proposals
装饰器给了js/ts又一次大的变化,很多高级便捷的功能成为了可能。下面的例子展示了一个简单的@loggedMethod
功能。
function loggedMethod(headMessage = "LOG:") {
return function actualDecorator(originalMethod: any, context: ClassMethodDecoratorContext) {
const methodName = String(context.name);
function replacementMethod(this: any, ...args: any[]) {
console.log(`${headMessage} Entering method '${methodName}'.`)
const result = originalMethod.call(this, ...args);
console.log(`${headMessage} Exiting method '${methodName}'.`)
return result;
}
return replacementMethod;
}
}
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
@loggedMethod("⚠️")
greet() {
console.log(`Hello, my name is ${this.name}.`);
}
}
const p = new Person("Ray");
p.greet();
const泛型
在泛型上可以定义const
修饰符,编译器将尽可能的匹配常量类型,这使得调用者不需要总是显式的写上as const
。
declare function foo<const T extends readonly string[]>(args: T): void;
// T is readonly ["a", "b", "c"]
foo(["a", "b" ,"c"]);
5.1
5.2
目前5.2版本尚未release,版本计划见TypeScript 5.2 Iteration Plan
using关键字
https://github.com/microsoft/TypeScript/pull/54505
using也是一个ECMA新标准,处于Stage 3。
using类似const,定义一个可以被释放的常量。在离开作用域时,using对象的Symbol.dispose
方法会被调用。
同时还支持异步的await using
。
function foo() {
const getResource = () => {
return {
[Symbol.dispose]: () => {
console.log('disposed')
}
}
}
using resource = getResource();
// resource will be disposed when return
}
Decorator Metadata
https://github.com/microsoft/TypeScript/issues/53461
允许装饰器在目标对象上添加元信息。
function meta(key, value) {
return (_, context) => {
context.metadata[key] = value;
};
}
@meta('a' 'x')
class C {
@meta('b', 'y')
m() {}
}
C[Symbol.metadata].a; // 'x'
C[Symbol.metadata].b; // 'y'