定义方式
在 TypeScript 中,以下几种方式用于定义对象:
接口(Interface)
常用场景:
接口用于定义对象的结构,尤其是当对象结构比较复杂、需要复用或者要用于类的类型定义时。
接口非常适合用于定义 API 的数据结构或者复杂的对象类型。
示例:
1 | interface Person { |
类型别名(Type Alias)
常用场景:
类型别名可以定义对象类型,也可以定义联合类型、交叉类型等。
它非常灵活,适用于定义各种复杂类型,包括对象类型。
示例:
1 | type Person = { |
类(Class)
常用场景:
类用于定义具有特定行为和属性的对象。它适用于面向对象编程,尤其是在需要创建多个具有相同结构和行为的对象实例时。
示例:
1 | class Person { |
对象字面量(Object Literal)
常用场景:
对象字面量通常用于简单的数据结构或者临时使用的对象。
对于复杂对象结构或需要复用的类型定义,不建议使用这种方式。
示例:
1 | const person: { name: string; age: number; isActive: boolean } = { |
使用场景
接口(Interface) 和 类型别名(Type Alias) 是最常用的定义对象类型的方式,尤其是在大型应用程序或库中。
接口在扩展和复用方面有优势,而类型别名更为灵活,适合定义复杂的联合类型和交叉类型。
类(Class) 在需要封装对象行为时使用较多,例如在面向对象编程中创建多个实例时。
它提供了更多的功能,如构造函数、方法和继承。
对象字面量(Object Literal) 适用于简单场景,通常在局部变量或临时对象的定义中使用较多。
总体来说,接口和类型别名是最常见的选择,特别是在 TypeScript 的类型系统中,它们提供了最好的类型安全和灵活性。
类型定义文件
在 TypeScript 中,如果你有一个类型定义文件(通常是以 .d.ts
为扩展名的文件)。
个人建议类型定义都放在src/assets/types/
文件夹下。
全局使用
注意
命名要防止和其他地方冲突。
如果你的类型定义文件不使用模块系统,而是定义了全局类型,你可以直接在 TypeScript 项目的 tsconfig.json
文件中通过 include
来包含这些类型定义文件。
TypeScript 编译器会自动识别并将其应用于整个项目。
我这里把全局使用的类型定义都放在了src/assets/types/
下。
全局定义的名称不能重复,全局定义的类型不需要导出(export)
。
1 | interface ZUser { |
我的项目是引用了tsconfig.app.json
,所以我在该文件中添加:
1 | { |
配置过后,可能需要重启IDEA才能生效。
引用方式使用
user.d.ts
1 | export interface User { |
使用
1 | import type { ZUser } from '@/assets/types/user' |
可选属性和可空属性
- 可选属性:使用问号
?
,表示属性可能存在也可能不存在。 - 可空属性:在属性类型中添加
null
或undefined
,表示属性可以是指定类型,也可以是null
或undefined
。
可选属性
1 | interface User { |
可空属性
1 | interface Person { |
类型断言
类型断言:
类型断言允许开发者手动指定一个值的类型,有两种语法形式:
- 尖括号语法:
<类型>值
as
语法:值 as 类型
1 | // 类型断言 |
泛型
无泛型
不使用泛型时
1 | interface ZResult { |
单泛型
1 | interface ZResult<T> { |
这时候可以这样用
1 | // 使用ZResult接口并指定obj的类型为User |
多泛型
1 | interface ZResult<T, U> { |
使用示例
1 | // 使用ZResult接口并指定obj的类型为User,extraInfo的类型为ExtraInfo |
扩展接口属性
window是全局唯一的对象,在JS中我们可以方便的添加任何我们想全局访问的属性,但是在TS中不行。
我们需要扩展 Window 接口
添加一个全局的定义文件 globals.d.ts
1 | interface Window { |
这样我们就可以在TS中使用了
1 | window.loginUser = {name:"张三"} |
添加属性
在 TypeScript 中,如果你需要在现有类型中添加或修改属性,有几种常见的方法可以实现。这些方法包括扩展接口、使用类型交叉、和声明合并。
下面详细介绍这些方法:
接口扩展
如果你有一个已有的接口或类型,想要在其基础上添加新属性,可以通过继承或扩展接口来实现。这通常通过声明合并来完成。
示例:
假设你有一个基础接口 Person
,现在你想要在其基础上添加一个 age
属性。
1 | // 基础接口 |
使用类型交叉
类型交叉允许你创建一个新类型,它结合了多个类型的属性。这种方式可以用于组合现有类型,或者在类型定义中添加新的属性。
示例:
1 | // 基础类型 |
类型别名与交叉类型
除了使用接口,你也可以使用类型别名和交叉类型来实现类似的效果。这在处理复杂类型或需要快速组合类型时特别有用。
示例:
1 | // 基础类型 |
模块扩展
如果你需要扩展模块的类型(例如,window
对象),可以在模块扩展中定义新的属性。
示例:
1 | // globals.d.ts |
然后在代码中使用扩展后的 window
属性:
1 | // 在 TypeScript 文件中 |
在类中添加属性
如果你正在处理类类型,可以直接在类中添加新属性或方法。
示例:
1 | class Person { |
总结
- 接口扩展:使用声明合并来扩展已有接口。
- 类型交叉:使用交叉类型 (
&
) 来组合多个类型。 - 模块扩展:扩展模块的类型以添加新属性。
- 类扩展:在类中添加新的属性或方法。