错误和异常处理
TypeScript 允许您使用标准 JavaScript 错误处理机制捕获和处理错误:
Try-Catch-Finally 块:
您还可以处理不同类型的错误:
自定义错误类型:
可以通过扩展 Error 来指定更具体的错误 class
:
混合类
Mixin 类允许您将多个类的行为组合并组合成一个类。它们提供了一种重用和扩展功能的方法,而不需要深层继承链。
异步语言特性
由于 TypeScript 是 JavaScript 的超集,因此它内置了 JavaScript 的异步语言功能,例如:
Promises:
Promise 是一种处理异步操作及其结果的方法,使用 .then()
和等方法 .catch()
来处理成功和错误条件。
要了解更多信息: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Async/await:
Async/await 关键字是一种为处理 Promise 提供看起来更同步的语法的方法。async
关键字用于定义异步函数,并且 await
关键字在异步函数中使用以暂停执行,直到 Promise 被解决或拒绝。
要了解更多信息:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
TypeScript 很好地支持以下 API:
Fetch API:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
Web Workers:
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
Shared Workers:
https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker
WebSocket:
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
迭代器和生成器
TypeScript 很好地支持交互器和生成器。
迭代器是实现迭代器协议的对象,提供了一种逐个访问集合或序列元素的方法。它是一个包含指向迭代中下一个元素的指针的结构。他们有一个 next()
方法返回序列中的下一个值以及指示序列是否为 的布尔值 done
。
生成器是使用 function*
简化迭代器创建的语法定义的特殊函数。它们使用 yield
关键字来定义值的序列,并在请求值时自动暂停和恢复执行。
生成器使创建迭代器变得更加容易,并且对于处理大型或无限序列特别有用。
例子:
TypeScript 还支持异步迭代器和异步生成器。
要了解更多信息:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator
TsDocs JSDoc 参考
使用 JavaScript 代码库时,可以通过使用 JSDoc 注释和附加注释来提供类型信息,帮助 TypeScript 推断正确的类型。
例子:
此链接提供了完整文档:
https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
从版本 3.7 开始,可以从 JavaScript JSDoc 语法生成 .d.ts 类型定义。更多信息可以在这里找到:
https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html
@types
@types 组织下的包是特殊的包命名约定,用于为现有 JavaScript 库或模块提供类型定义。例如使用:
将在您当前的项目中安装 lodash
的类型定义。
要为 @types 包的类型定义做出贡献,请向 https://github.com/DefinitelyTyped/DefinitelyTyped 提交pr请求。
JSX
JSX (JavaScript XML) 是 JavaScript 语言语法的扩展,允许您在 JavaScript 或 TypeScript 文件中编写类似 HTML 的代码。它通常在 React 中用来定义 HTML 结构。
TypeScript 通过提供类型检查和静态分析来扩展 JSX 的功能。
要使用 JSX,您需要在文件 tsconfig.json
中设置 jsx
编译器选项。两个常见的配置选项:
- “preserve”: 触发 .jsx 文件且 JSX 不变. 此选项告诉 TypeScript 按原样保留 JSX 语法,而不是在编译过程中对其进行转换。 如果您有单独的工具(例如 Babel)来处理转换,则可以使用此选项。
- “react”: 启用 TypeScript 的内置 JSX 转换。 将使用 React.createElement 。
所有选项均可在此处使用:
https://www.typescriptlang.org/tsconfig#jsx
ES6 模块
TypeScript 确实支持 ES6 (ECMAScript 2015) 和许多后续版本。这意味着您可以使用 ES6 语法,例如箭头函数、模板文字、类、模块、解构等等。
要在项目中启用 ES6 功能,您可以在 tsconfig.json
中指定 target
属性。
配置示例:
ES7 求幂运算符
求幂 (**
) 运算符计算通过将第一个操作数进行第二个操作数的幂获得的值。它的功能与 Math.pow()
类似,但增加了接受 BigInts 作为操作数的功能。TypeScript 完全支持在 tsconfig.json
文件中设置 target
为 es2016
或更大版本来使用此运算符。
for-await-of 语句
这是 TypeScript 完全支持的 JavaScript 功能,它允许您从目标版本 es2018
迭代异步可迭代对象。
New target 元属性
您可以在 TypeScript 中使用 new.target
元属性,该属性使您能够确定是否使用 new 运算符调用函数或构造函数。它允许您检测对象是否是由于构造函数调用而创建的。
动态导入表达式
可以使用 TypeScript 支持的动态导入 ECMAScript 建议有条件地加载模块或按需延迟加载模块。
TypeScript 中动态导入表达式的语法如下:
“tsc –watch”
此命令使用 --watch
参数启动 TypeScript 编译器,能够在修改 TypeScript 文件时自动重新编译它们。
从 TypeScript 4.9 版本开始,文件监控主要依赖于文件系统事件,如果无法建立基于事件的观察程序,则会自动诉诸轮询。
默认声明
当为变量或参数分配默认值时,将使用默认声明。这意味着如果没有为该变量或参数提供值,则将使用默认值。
可选链
可选的链接运算符 ?.
与常规点运算符 (.
) 一样用于访问属性或方法。但是,它通过优雅处理 undefined
和 null
来终止表达式并返回 undefined
,而不是抛出错误。
空合并运算符
如果 ??
左侧是 null
或者 undefined
,则空合并运算符返回右侧值,否则,它返回左侧值。
模板字符串类型
模板字符串类型允许在类型级别操作字符串值并基于现有字符串生成新的字符串类型。它们对于从基于字符串的操作创建更具表现力和更精确的类型非常有用。
函数重载
函数重载允许您为同一函数名定义多个函数签名,每个函数签名具有不同的参数类型和返回类型。当您调用重载函数时,TypeScript 使用提供的参数来确定正确的函数签名:
递归类型
递归类型是可以引用自身的类型。 这对于定义具有分层或递归结构(可能无限嵌套)的数据结构非常有用,例如链表、树和图。
递归条件类型
可以使用 TypeScript 中的逻辑和递归来定义复杂的类型关系。让我们简单地分解一下:
条件类型:允许您基于布尔条件定义类型:
递归:是指在自己的定义中引用自身的类型定义:
递归条件类型结合了条件逻辑和递归。这意味着类型定义可以通过条件逻辑依赖于自身,从而创建复杂且灵活的类型关系。
Node 中的 ECMAScript 模块支持
Node.js 从 15.3.0 版本开始添加了对 ECMAScript 模块的支持,而 TypeScript 从 4.7 版本开始增加了对 Node.js 的 ECMAScript 模块支持。可以通过将 tsconfig.json
文件中的module
属性的值设置为 nodenext
来启用此支持。这是一个例子:
Node.js 支持两种模块文件扩展名:.mjs
的ES 模块和 .cjs
的CommonJS 模块。TypeScript 中的等效文件扩展名适用 .mts
于 ES 模块和 .cts
于CommonJS 模块。当 TypeScript 编译器将这些文件转译为 JavaScript 时,它将分别创建 .mjs
和 .cjs
文件。
如果您想在项目中使用 ES 模块,可以type在 package.json 文件中将该属性设置为”module”。这指示 Node.js 将项目视为 ES 模块项目。
此外,TypeScript 还支持 .d.ts 文件中的类型声明。这些声明文件为用 TypeScript 编写的库或模块提供类型信息,允许其他开发人员通过 TypeScript 的类型检查和自动完成功能来利用它们。
断言函数
在 TypeScript 中,断言函数是根据返回值指示特定条件验证的函数。在最简单的形式中,断言函数检查提供的谓词,并在谓词计算结果为 false 时引发错误。
或者可以声明为函数表达式:
断言函数与类型保护有相似之处。类型保护最初是为了执行运行时检查并确保值的类型在特定范围内而引入的。具体来说,类型保护是一个计算类型谓词并返回指示谓词是真还是假的布尔值的函数。这与断言函数略有不同,断言函数的目的是在不满足谓词时抛出错误而不是返回 false。
类型保护示例:
可变参数元组类型
可变元组类型是 TypeScript 4.0 版本中引入的一个功能,让我们通过回顾什么是元组来开始学习它们:
元组类型是一个具有定义长度的数组,并且每个元素的类型已知:
术语”可变参数”意味着不定数量(接受可变数量的参数)。
可变参数元组是一种元组类型,它具有以前的所有属性,但确切的形状尚未定义:
在前面的代码中我们可以看到元组形状是由T传入的泛型定义的。
可变参数元组可以接受多个泛型,这使得它们非常灵活:
使用新的可变参数元组,我们可以使用:
- 元组类型语法中的扩展现在可以是通用的,因此即使我们不知道我们正在操作的实际类型,我们也可以表示元组和数组上的高阶操作
- 其余元素可以出现在元组中的任何位置。
例子:
装箱类型
装箱类型是指用于将基本类型表示为对象的包装对象。这些包装器对象提供了原始值无法直接使用的附加功能和方法。
当你访问原始 string
上的 charAt
或者 normalize
方法时,JavaScript 将其包装在 String
类型的对象中,调用该方法,然后丢弃该对象
示范:
TypeScript 通过为原语及其相应的对象包装器提供单独的类型来表示这种区别:
- string => String
- number => Number
- boolean => Boolean
- symbol => Symbol
- bigint => BigInt
通常不需要盒装类型。避免使用装箱类型,而是使用基元类型,例如 string
代替 String
。
TypeScript 中的协变和逆变
协变和逆变用于描述在处理类型的继承或赋值时关系如何工作。
协变意味着类型关系保留继承或赋值的方向,因此如果类型 A 是类型 B 的子类型,则类型 A 的数组也被视为类型 B 的数组的子类型。这里需要注意的重要事项是维持子类型关系,这意味着协变接受子类型但不接受超类型。
逆变意味着类型关系颠倒了继承或赋值的方向,因此如果类型 A 是类型 B 的子类型,则类型 B 的数组被视为类型 A 数组的子类型。子类型关系颠倒了,这意味着该逆变接受超类型但不接受子类型。
注意:双变量意味着同时接受超类型和子类型。
示例:假设我们有一个适合所有动物的空间和一个专门适合狗的单独空间。
在协方差中,您可以将所有狗放入动物空间中,因为狗是一种动物。但你不能把所有的动物都放在狗的空间里,因为可能还有其他动物混在一起。
在逆变中,您不能将所有动物放入狗空间中,因为动物空间也可能包含其他动物。然而,你可以把所有的狗都放在动物空间里,因为所有的狗也是动物。
在 TypeScript 中,数组的类型关系是协变的,而函数参数的类型关系是逆变的。这意味着 TypeScript 同时表现出协变和逆变,具体取决于上下文。
类型参数的可选方差注释
从 TypeScript 4.7.0 开始,我们可以使用out和in关键字来具体说明方差注释。
对于协变,使用out关键字:
对于逆变,使用in关键字:
模板字符串模式索引签名
模板字符串模式索引签名允许我们使用模板字符串模式定义灵活的索引签名。 此功能使我们能够创建可以使用特定字符串键模式进行索引的对象,从而在访问和操作属性时提供更多控制和特异性。
TypeScript 4.4 版开始允许符号和模板字符串模式的索引签名。
satisfies操作符
satisfies
允许您检查给定类型是否满足特定接口或条件。换句话说,它确保类型具有特定接口所需的所有属性和方法。这是确保变量适合类型定义的一种方法。
下面是一个示例:
仅类型导入和导出
仅类型导入和导出允许您导入或导出类型,而无需导入或导出与这些类型关联的值或函数。 这对于减小捆绑包的大小很有用。
要使用仅类型导入,您可以使用import type
关键字。
TypeScript 允许在仅类型导入中使用声明和实现文件扩展名(.ts、.mts、.cts 和 .tsx),无论allowImportingTsExtensions
设置如何。
例如:
以下是支持的形式:
使用声明和显式资源管理
”using”声明是块范围的、不可变的绑定,类似于”const”,用于管理一次性资源。 当使用值初始化时,该值的”Symbol.dispose”方法将被记录,并随后在退出封闭块作用域时执行。
这是基于 ECMAScript 的资源管理功能,该功能对于在对象创建后执行基本的清理任务非常有用,例如关闭连接、删除文件和释放内存。
笔记:
- 由于最近在 TypeScript 5.2 版中引入,大多数运行时缺乏本机支持。 您将需要以下功能的填充:
Symbol.dispose
、Symbol.asyncDispose
、DisposableStack
、AsyncDisposableStack
、SuppressedError
。
- 此外,您需要按如下方式配置 tsconfig.json:
例子:
该代码将记录:
符合处置条件的资源必须遵守 Disposable
接口:
“using”声明在堆栈中记录资源处置操作,确保它们以与声明相反的顺序处置:
即使发生后续代码或异常,也保证会释放资源。 这可能会导致处置可能引发异常,并可能抑制另一个异常。 为了保留有关被抑制错误的信息,引入了一个新的本机异常”SuppressedError”。
使用声明等待
”await using”声明处理异步一次性资源。 该值必须具有”Symbol.asyncDispose”方法,该方法将在块末尾等待。
对于异步可处置资源,它必须遵守”Disposable”或”AsyncDisposable”接口:
代码日志:
语句中允许使用”using”和”await using”声明:“for”、“for-in”、“for-of”、“for-await-of”、“switch”。
导入属性
TypeScript 5.3 的导入属性(导入标签)告诉运行时如何处理模块(JSON 等)。这通过确保干净的导入来提高安全性,并与内容安全策略 (CSP) 保持一致,以实现更安全的资源加载。TypeScript 确保它们有效,但让运行时处理它们的解释以进行特定的模块处理。
示例:
使用动态导入: