TypeScript 5.0 正式发布!

101 阅读2分钟

2023年3月7日,TypeScript5.0正式发布!此版本带来了许多新功能,旨在使TypeScript更小、更简单、更快.TypeScript5.0实现了新的装饰器标准、更好地支持Node和大打构建工具中的ESM项目的功能,库作者控制泛型推导的新方法、扩展了JSDoc功能、简化了配置,并进行了许多其他改进。

可以通过以下npm命令开始使用TypeScript5.0:

 npm install -D typescript

以下是TypeScript5.0的主要更新:

  • 全新装饰器
  • const 类型参数
  • extends 支持多配置文件
  • 所有枚举都是联合枚举
  • --moduleResolution bundler
  • 自定义解析标志
  • --verbatimModuleSyntax
  • 支持export type *
  • JSDoc支持@satisfies
  • JSDoc支持@overload
  • 编辑器中不区分大小写的导入排序
  • 完善switch/case
  • 优化速度、内存和包大小
  • 其他重大更改和弃用

全新装饰器

装饰器是即将推出的ECMAScript特性,它允许我们可重用的方式自定义类及其成员。 考虑以下代码:

  class Person{
      name:String;
      constructor(name:string){
         this.name=name;
      }
      greet(){
        console.log(`Hello,my name is ${this.name}.`)
      }
  }
  const p = new Person("Ray");
  p.greet();
  

这里的 greet 方法很简单,在实际中它内部可能会更复杂,比如需要执行异步逻辑,或者进行递归,亦或是有副作用等。那就可能需要使用console.log来调试greet:

class Person {  
    name: string;  
    constructor(name: string) {  
        this.name = name;  
    }  
  
    greet() {  
        console.log("LOG: Entering method.");  
  
        console.log(`Hello, my name is ${this.name}.`);  
  
        console.log("LOG: Exiting method.")  
    }  
}

如果有一种方法可以为每种方法做到这一点,可能会很好。 这就是装饰器等用武之地。我们可以编写一个名为loggedMethod的函授,如下所示:

function loggedMethod(originalMethod: any, _context: any) {  
  
    function replacementMethod(this: any, ...args: any[]) {  
        console.log("LOG: Entering method.")  
        const result = originalMethod.call(this, ...args);  
        console.log("LOG: Exiting method.")  
        return result;  
    }  
  
    return replacementMethod;  
}

这里用了很多any,可以暂时忽略,这样可以让例子尽可能得简单。

这里,loggedMethod 需要传入一个参数(originalMethod) 并返回一个函数。执行过程如下:

  • 打印:LOG:Entering method.
  • 将this及其所有参数传递给原始方法
  • 打印:LOG:Exiting methods.
  • 返回原始方法的执行结果

现在我们就可以使用 loggedMethod 来修饰 greet 方法:

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();

输出如下:

LOGEntering method.  
Hello, my name is Ray.  
LOGExiting method.

这里我们在 greet 上面使用了 loggedMethod 作为装饰器——注意这里的写法:@loggedMethod。这样,它会被原始方法和 context 对象调用。因为 loggedMethod 返回了一个新函数,该函数替换了 greet 的原始定义。

loggedMethod 的第二个参数被称为“ context 对象”,它包含一些关于如何声明装饰方法的有用信息——比如它是 #private 成员还是静态成员,或者方法的名称是什么。下面来重写 loggedMethod 以利用它并打印出被修饰的方法的名称。