TypeScript 5.8 新特性:erasableSyntaxOnly

3,439 阅读2分钟

最近升级了5.8,碰到了一个问题: 启用 “erasableSyntaxOnly” 时,不允许使用此语法。ts(1294)

遂收集了一些erasableSyntaxOnly的资料分享一下 参考:

github.com/microsoft/T…

www.totaltypescript.com/erasable-sy…

oida.dev/erasable-sy…

什么是 erasableSyntaxOnly?

erasableSyntaxOnly 是一个编译器标志,它的主要目的是确保我们只使用那些在编译后不会生成额外 JavaScript 代码的 TypeScript 特性。简单来说,它要求我们只使用"可擦除"的语法。

哪些特性会被禁用?

这个标志会禁用以下特性:

  1. 枚举(Enums)
// 报错!启用 “erasableSyntaxOnly” 时,不允许使用此语法。ts(1294)
enum Status {
  Success = "Success",
  Error = "Error"
}
  1. 命名空间(Namespaces)
// 报错!启用 “erasableSyntaxOnly” 时,不允许使用此语法。ts(1294)
namespace Utils {
  export const version = "1.0.0";
}
  1. 类中的参数属性
// 报错!启用 “erasableSyntaxOnly” 时,不允许使用此语法。ts(1294)
class User {
  constructor(private name: string) {}
}

为什么需要这个标志?

1. 运行时性能考虑

这些特性在编译后会生成额外的 JavaScript 代码,增加了代码体积。以枚举为例,它会被编译成一个双向映射的对象,这在运行时会产生不必要的开销。

2. 与 Node.js 的 TypeScript 支持相关

Node.js 最近添加了对 TypeScript 的原生支持,但它只支持"可擦除"的语法。这意味着如果你想要在 Node.js 中直接运行 TypeScript 文件,就需要避免使用这些会生成额外代码的特性。

3. 未来 JavaScript 类型系统的发展

目前有多个提案正在讨论将类型系统引入JavaScript,比如"types as comments"提案。这些提案都只支持"可擦除"的语法,因为浏览器需要能够直接忽略类型信息。

image.png

实际开发中的影响

替代方案

  1. 枚举的替代方案:
// 替代枚举
const Status = {
  Success"Success",
  Error"Error"as const;

type StatusType = typeof Status[keyof typeof Status];
  1. 命名空间的替代:
// 使用模块替代命名空间
export const Utils = {
  version"1.0.0"
};

导入路径别名的处理

erasableSyntaxOnly也会影响tsconfig.json中的paths配置。建议使用package.json中的imports字段来处理导入路径别名,这是Node.js原生支持的方式。

个人建议

  1. 在新项目中考虑启用erasableSyntaxOnly,这样可以确保代码更加轻量和可维护。
  2. 现有项目不要急于迁移,可以逐步减少对这些特性的使用。
  3. 在编写库或框架时,特别要注意避免使用这些特性,因为它们可能会影响最终打包的大小和性能。
  4. 关注TypeScriptJavaScript类型系统的发展,为未来的变化做好准备。

总结

erasableSyntaxOnly会改变我们的开发习惯,但是它的引入也反映了TypeScript团队对代码质量和性能的重视。 从长远来看,有助于我们写出更加高效和可维护的代码。