带你看看 TypeScript 5.0 的新特性
一、写在前面
TypeScript 5.0 已经于 2023 年 3 月 16 日发布了,带来了许多新功能,同时也在性能方面进行了优化,下面让我们来一起看看新版 TypeScript 中比较有重要的变化吧。
二、新特性
2-1、速度、包体积优化
首先是新版本性能的提升,5.0 版本在构建速度、包体积方面都有着不错的优化,下面这张表格是 5.0 版本相对于 4.9 的性能提升幅度:
项目 | 相对于 TS 4.9 的优化幅度 |
---|---|
material-ui 构建时间 | 90% |
TypeScript 编译器启动时间 | 89% |
TypeScript 编译器自构建时间 | 87% |
Outlook Web 构建时间 | 82% |
VS Code 构建时间 | 80% |
npm 包大小 | 59% |
TypeScript 5.0 具体做了什么来优化性能呢?
- 首先是将
namespace
迁移到module
,这样可以应用更多现代构建工具的特性来进行优化(如作用域提升),并移除一些已弃用的代码,将包大小减少了约 26.4 MB。 - 其次是 TS 精简了编译器内部的对象所存储的数据,减少了内存使用量。
- 然后是在一些特定领域进行优化,如在闭包中偶尔使用
var
,而不是let
或const
来提高解析性能。
总的来说,大多数 TypeScript 项目都能从 TypeScript 5.0 中获得 10% 到 20% 性能提升。
2-2、新的装饰器标准
装饰器这个东西,写 ts 的小伙伴一定不会陌生,虽然它还不是一个标准的 js 特性,但 ts 已经在之前的版本就支持了“实验性”装饰器。而在最新的 5.0 版本中,装饰器语法将不再是一个“实验性”的语法,也不需要在编译选项中加入--experimentalDecorators
配置项了(虽然在新版本,这个编译选项依旧会存在),TypeScript 5.0 将会原生支持装饰器语法!
下面让我们来看一个装饰器的例子吧——
首先我们有一个很简单的类:
class Person {name: string;constructor(name: string) {this.name = name;}greet() {console.log(`Hello, my name is ${this.name}.`);}
}const p = new Person("zy");
p.greet();
我们想在这个类的greet
函数中加点日志,并记录调用函数的名称,那么最简单的方式是这样做:
class Person {name: string;constructor(name: string) {this.name = name;}greet() {console.log("LOG: Entering method greet.");console.log(`Hello, my name is ${this.name}.`);console.log("LOG: Exiting method greet.");}
}const p = new Person("zy");
p.greet();
但如果我们想给更多的函数都加上类似的功能,那用装饰器就非常合适了,比如我们可以编写一个loggedMethod
,如下所示:
function loggedMethod(originalMethod: any,context: ClassMethodDecoratorContext
) {const methodName = String(context.name);function replacementMethod(this: any, ...args: any[]) {console.log(`LOG: Entering method '${methodName}'.`);const result = originalMethod.call(this, ...args);console.log(`LOG: Exiting method '${methodName}'.`);return result;}return replacementMethod;
}
这样我们用loggedMethod
这个装饰器来装饰这个函数,就可以实现上述效果了:
class Person {name: string;constructor(name: string) {this.name = name;}@loggedMethodgreet() {console.log(`Hello, my name is ${this.name}.`);}
}const p = new Person("zy");
p.greet();// Output:
//
// LOG: Entering method 'greet'.
// Hello, my name is zy.
// LOG: Exiting method 'greet'.
我们甚至可以创建一个“返回装饰器函数的函数”,这样我们就可以为装饰器开发更多定制化更多的功能,比如说,我想自定义输出到控制台的字符串的前缀:
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;};
}
这样我们在loggedMethod
被用作装饰器之前调用它,就可以实现传入定制的字符串作为控制台输出字符串的前缀了:
class Person {name: string;constructor(name: string) {this.name = name;}@loggedMethod("LOG:")greet() {console.log(`Hello, my name is ${this.name}.`);}
}const p = new Person("zy");
p.greet();// Output:
//
// LOG: Entering method 'greet'.
// Hello, my name is zy.
// LOG: Exiting method 'greet'.
2-3、const
类型参数
在推断对象的类型时,ts 通常会选择一种通用的类型。例如,在这种情况下,会将names
的类型推断为string []
:
type HasNames = { readonly names: string[] };
function getNamesExactly<T extends HasNames>(arg: T): T["names"] {return arg.names;
}// Inferred type: string[]
const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] });
推断成string []
固然没有问题,但由于names
是readonly
的,而推断出的类型不是readonly
的,这就会产生一些困扰。虽然我们可以通过添加as const
来解决这个问题,就像这样:
// The type we wanted:
// readonly ["Alice", "Bob", "Eve"]
// The type we got:
// string[]
const names1 = getNamesExactly({ names: ["Alice", "Bob", "Eve"] });// Correctly gets what we wanted:
// readonly ["Alice", "Bob", "Eve"]
const names2 = getNamesExactly({ names: ["Alice", "Bob", "Eve"] } as const);
但这样写很麻烦,且容易被忘掉。所以在 TypeScript 5.0 中,我们可以将const
修饰符直接添加到类型参数声明中,将常数类型推理变为默认值:
type HasNames = { names: readonly string[] };
function getNamesExactly<const T extends HasNames>(arg: T): T["names"] {
// ^^^^^return arg.names;
}// Inferred type: readonly ["Alice", "Bob", "Eve"]
// Note: Didn't need to write 'as const' here
const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] });
具体细节:https://github.com/microsoft/TypeScript/pull/51865
2-4、extends
配置项支持多个配置文件
extends
配置项支持多个配置文件其实是我个人认为 TypeScript 5.0 中最实用的一个特性了。当我们使用tsconfig.json
管理多个项目时,很多情况下都会在一个“基准”配置文件上进行配置扩展,比如下面这样:
// packages/front-end/src/tsconfig.json
{"extends": "../../../tsconfig.base.json","compilerOptions": {"outDir": "../lib",// ...}
}
但是,在很多时候,我们会希望从多个配置文件进行扩展,但 TypeScript 4.9 及以前的版本都不支持这个功能!而好消息是,Typescript 5.0 现在允许该 extends 字段引入多个配置路径。例如,下面这种写法:
// tsconfig1.json
{"compilerOptions": {"strictNullChecks": true}
}// tsconfig2.json
{"compilerOptions": {"noImplicitAny": true}
}// tsconfig.json
{"extends": ["./tsconfig1.json", "./tsconfig2.json"],"files": ["./index.ts"]
}
在这个例子中,strictNullChecks
和noImplicitAny
都会在最终的tsconfig.json
中生效。
注意,如果这些引入的配置文件中有字段冲突,那么后引入的字段会覆盖先引入的字段。
具体细节:https://github.com/microsoft/TypeScript/pull/50403
2-5、所有枚举变为联合枚举
TypeScript 最初在设计枚举类型时,只不过是将它们视为一组具有相同类型的数字常量,比如下面这个枚举E
:
enum E {Foo = 10,Bar = 20,
}
E.Foo
、E.Bar
相比于普通的变量,唯一特别之处在于它可以分配给任何类型为E
的东西。除此之外,他们几乎和numbers
类型没什么区别,就像下面这样:
function takeValue(e: E) {}takeValue(E.Foo); // works
takeValue(123); // error!
直到 TypeScript 2.0 引入了枚举文字类型,枚举才变得特殊。枚举文字类型为每个枚举成员提供了自己的类型,并将枚举本身变成了每个成员类型的集合。它们还允许我们仅引用枚举类型的一个子集,并缩小这些类型的范围,就如同下面展示的枚举Color
:
// Color is like a union of Red | Orange | Yellow | Green | Blue | Violet
enum Color {Red, Orange, Yellow, Green, Blue, /* Indigo */, Violet
}// Each enum member has its own type that we can refer to!
type PrimaryColor = Color.Red | Color.Green | Color.Blue;function isPrimaryColor(c: Color): c is PrimaryColor {// Narrowing literal types can catch bugs.// TypeScript will error here because// we'll end up comparing 'Color.Red' to 'Color.Green'.// We meant to use ||, but accidentally wrote &&.return c === Color.Red && c === Color.Green && c === Color.Blue;
}
而在某些场景——比如枚举成员使用函数调用初始化的时候,TypeScript 无法计算出枚举值的集合,它就会放弃联合枚举,转而使用旧的枚举策略。
而 TypeScript 5.0 解决了这个问题,它通过为每个枚举成员创建唯一类型,将所有枚举都变成联合枚举。这样,我们在所有情况下的枚举值,都将是联合枚举。
具体细节:https://github.com/microsoft/TypeScript/pull/50528
2-6、--moduleResolution
配置项支持bundler
选项
TypeScript 4.7 在--module
和--moduleResolution
配置项中引入了node16
和nodenext
选项。这些选项能更好地模拟 Node.js 中 ECMAScript 模块的查找规则。然而,这种模式有很多限制,例如,在 Node.js 的 ECMAScript 模块中,任何相对导入都需要包含文件扩展名:
// entry.mjs
import * as utils from "./utils"; // wrong - we need to include the file extension.import * as utils from "./utils.mjs"; // works
但随着前端技术的发展,这种查找规则已经落伍了。大多数现代打包工具在 Node.js 中使用 ECMAScript 模块和 CommonJS 模块查找规则的融合。所以为了模拟打包工具的工作方式,TypeScript 现在引入了一种新策略:--moduleResolution bundler
.
{"compilerOptions": {"target": "esnext","moduleResolution": "bundler"}
}
如果你在使用像 Vite、esbuild、swc、Webpack、Parcel 等打包工具,那么bundler
这个配置会非常合适。
具体细节:https://github.com/microsoft/TypeScript/pull/51669
2-7、支持export type *
在 TypeScript 3.8 引入类型导入/导出时,是不允许 export _ from "module"
或 export _ as xx from "module"
这样的类型导出的。TypeScript 5.0 添加了对这两种类型导出语法的支持:
// models/vehicles.ts
export class Spaceship {// ...
}// models/index.ts
export type * as vehicles from "./vehicles";// main.ts
import { vehicles } from "./models";function takeASpaceship(s: vehicles.Spaceship) {// ok - `vehicles` only used in a type position
}function makeASpaceship() {return new vehicles.Spaceship();// ^^^^^^^^// 'vehicles' cannot be used as a value because it was exported using 'export type'.
}
详情请见:https://github.com/microsoft/TypeScript/pull/52217
相关文章:
带你看看 TypeScript 5.0 的新特性
一、写在前面 TypeScript 5.0 已经于 2023 年 3 月 16 日发布了,带来了许多新功能,同时也在性能方面进行了优化,下面让我们来一起看看新版 TypeScript 中比较有重要的变化吧。 二、新特性 2-1、速度、包体积优化 首先是新版本性能的提升&…...
C语言预处理条件语句的 与或运算
C语言预处理条件语句的 与或运算 1.#ifdef 与或运算 #ifdef (MIN) && (MAX) ----------------------------错误使用 #if defined(MIN) && defined(MAX) ---------------- 正确使用 #ifdef (MIN) || (MAX) -----------------------------错误使用 …...

从零实现深度学习框架——学习率调整策略介绍
引言 本着“凡我不能创造的,我就不能理解”的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导。 要深入理解深度学习,从零开始创建的经验非常重要,从自己可以理解的角度出发,尽量不使用外部完备的框架前提下,实现我…...

系统架构:经典三层架构
引言 经典三层架构是分层架构中最原始最典型的分层模式,其他分层架构都是其变种或扩展,例如阿里的四层架构模式和DDD领域驱动模型。阿里的 四层架构模型在三层基础上增加了 Manager 层,从而形成变种四层模型;DDD架构则在顶层用户…...

数据结构--二叉树
目录1.树概念及结构1.1数的概念1.2数的表示2.二叉树概念及结构2.1二叉树的概念2.2数据结构中的二叉树2.3特殊的二叉树2.4二叉树的存储结构2.4.1顺序存储2.4.2链式存储2.5二叉树的性质3.堆的概念及结构3.1堆的实现3.1.1堆的创建3.1.2堆的插入3.1.3堆顶的删除3.1.4堆的代码实现3.…...

Keil5安装和使用小记
随着keil版本的更新,一些使用问题一随之产生。本文针对安装目前最新版本keil软件和使用问题做一些总结。 目录1 Keil5下载&安装1.1 官网下载链接1.2 软件安装1.2.1 安装说明1.2.2 关于 51 和 ARM 共存的问题1.3 软件破解2 pack包安装 & 破解2.1 下载2.2 安装…...

多机器人集群网络通信协议分析
本文讨论的是多机器人网络通信各层的情况和协议。 每个机器人连接一个数据传输通信模块(以下简称为数传,也泛指市面上的图传或图数一体的通信模块),数传之间进行组网来传递信息。 根据ISO的划分,网络通信的OSI模型分…...
【PyTorch】手把手带你快速搭建PyTorch神经网络
手把手带你快速搭建PyTorch神经网络1. 定义一个Class2. 使用上面定义的Class3. 执行正向传播过程4. 总结顺序相关资料话不多说,直接上代码1. 定义一个Class 如果要做一个神经网络模型,首先要定义一个Class,继承nn.Module,也就是i…...

【完整代码】用HTML/CSS制作一个美观的个人简介网页
【完整代码】用HTML/CSS制作一个美观的个人简介网页整体结构完整代码用HTML/CSS制作一个美观的个人简介网页——学习周记1HELLO!大家好,由于《用HTML/CSS制作一个美观的个人简介网页》这篇笔记有幸被很多伙伴关注,于是特意去找了之前写的完整…...

Java分布式事务(九)
文章目录🔥XA强一致性分布式事务实战_Atomikos介绍🔥XA强一致性分布式事务实战_业务说明🔥XA强一致性分布式事务实战_项目搭建🔥XA强一致性分布式事务实战_多数据源实现🔥XA强一致性分布式事务实战_业务层实现…...

基于深度学习的动物识别系统(YOLOv5清新界面版,Python代码)
摘要:动物识别系统用于识别和统计常见动物数量,通过深度学习技术检测日常几种动物图像识别,支持图片、视频和摄像头画面等形式。在介绍算法原理的同时,给出Python的实现代码、训练数据集以及PyQt的UI界面。动物识别系统主要用于常…...
K8S集群之-ETCD集群监控
### 生产ETCD集群监控核心指标 etcd服务存活状态 up{job~"kubernetes-etcd.*"}0 说明:up0代表服务挂掉 etcd是否有脱离情况 etcd_server_has_leader{job~"kubernetes-etcd.*"}0 说明:每个instance,该值应该都…...

一文弄懂熵、交叉熵和kl散度(相对熵)
一个系统中事件发生的概率越大,也就是其确定性越大,则其包含的信息量越少,可以认为一个事件的信息量就是该事件发生难度的度量,事件所包含的信息量越大则其发生的难度越大。并且相互独立的事件,信息量具有可加性。相互…...

10从零开始学Java之开发Java必备软件Intellij idea的安装配置与使用
作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者前言壹哥在前面的文章中,带大家下载、安装、配置了Eclipse这个更好用的IDE开发工具,并教会了大家如何在Ecli…...

04 - 进程参数编程
---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接:(更新中)Linux系统编程训练营 - 目录 文章目录1. 问题1.1 再论execve(...)1.2 main函数(默认进程入口)1.3 进程空间概要图1.4 编程实验:进程参数剖析1…...

【python进阶】你真的懂元组吗?不仅是“不可变的列表”
📚引言 🙋♂️作者简介:生鱼同学,大数据科学与技术专业硕士在读👨🎓,曾获得华为杯数学建模国家二等奖🏆,MathorCup 数学建模竞赛国家二等奖🏅,…...
《C++ Primer Plus》(第6版)第13章编程练习
《C Primer Plus》(第6版)第13章编程练习《C Primer Plus》(第6版)第13章编程练习1. Cd类2. 使用动态内存分配重做练习13. baseDMA、lacksDMA、hasDMA类4. Port类和VintagePort类《C Primer Plus》(第6版)第…...

【多线程】多线程案例
✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 ✨每日一语:we can not judge the value of a moment until it becomes a memory. 目 录🍝一. 单例模式🍤1. 饿汉模式实现🦪2. 懒汉模…...

【IoT】嵌入式驱动开发:IIC子系统
IIC有三种接口实现方式 三种时序对比: 图1 IIC子系统组成 图2 图3 IIC操作流程 设备端 1.i2c_get_adapter 2.i2c_new_device(相当于register设备) 3.I2c_put_adapter 驱动端 1.填充i2c_driver 2.i2c_add_driver(相当于register驱动) 3.在probe中建立访问方式 client相…...

DJ2-4 进程同步(第一节课)
目录 2.4.1 进程同步的基本概念 1. 两种形式的制约关系 2. 临界资源(critical resource) 3. 生产者-消费者问题 4. 临界区(critical section) 5. 同步机制应遵循的规则 2.4.2 硬件同步机制 1. 关中断 2. Test-and-Set …...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...