文章目录
TypeScript 中的类(class)是对象构建的核心,通过类成员定义属性、构造器和方法,使得代码更加结构化。本文将深入探讨 TypeScript 中类的成员,展示如何定义字段、构造器、方法等内容,帮助你更好地掌握 TypeScript 类的使用。
一、类概述
1. 什么是类?
在面向对象编程中,类是一种模板,通过它可以创建具有相同属性和方法的对象。TypeScript 基于 JavaScript 增强了类的功能,例如提供了更强的类型检查和类成员修饰符,使得代码在开发阶段就能捕捉到更多潜在错误。
2. TypeScript 类的基本定义
以下代码展示了一个最简单的空类:
class Point {
}
这段代码定义了一个名为 Point
的类,但还没有为其添加任何成员,因此在实例化后也不会有任何功能。
二、类成员概述
类成员包括字段、构造器、方法、访问器和索引签名等,这些元素共同定义了类的属性、初始化逻辑和行为。
三、字段 (Fields)
1. 字段声明
字段声明用于定义类中的变量,这些变量会作为实例的属性。TypeScript 中,字段默认是 public
的,也就是说可以在类外直接访问。
class Point {
x: number;
y: number;
}
const pt = new Point();
pt.x = 0;
pt.y = 0;
在这个例子中,Point
类有两个字段 x
和 y
,分别定义了坐标点的横纵坐标。在 TypeScript 中,如果不为字段指定类型,则默认类型为 any
。
2. 字段初始化
字段可以在声明时直接初始化:
class Point {
x = 0;
y = 0;
}
const pt = new Point();
console.log(`${
pt.x}, ${
pt.y}`); // 输出: 0, 0
TypeScript 会自动推断初始化字段的类型。在这个例子中,x
和 y
被推断为 number
类型。如果尝试将 string
赋值给它们,就会产生错误。
3. 严格的属性初始化 (--strictPropertyInitialization
)
TypeScript 的 --strictPropertyInitialization
设置会要求所有字段必须在构造函数中被初始化,否则会产生编译错误:
class BadGreeter {
name: string; // 错误: 属性 'name' 没有在构造函数中初始化
}
可以通过以下方式修复:
class GoodGreeter {
name: string;
constructor() {
this.name = "hello";
}
}
如果你希望跳过初始化检查,可以使用感叹号 !
:
class OKGreeter {
name!: string;
}
这样,name
字段在未初始化的情况下也不会报错。
4. 只读字段 (readonly
)
readonly
字段只能在声明或构造函数中赋值,其他地方修改会报错:
class Greeter {
readonly name: string = "world";
constructor(otherName?: string) {
if (otherName !== undefined) {
this.name = otherName;
}
}
}
在此例中,name
字段在构造函数外无法被修改。
四、构造函数 (Constructors)
构造函数用于实例化类时初始化对象。在 TypeScript 中,可以为构造函数添加类型注解、默认值和重载。
class Point {
x: number;
y: number;
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
}
1. 构造函数重载
构造函数支持多种参数签名:
class Point {
x: number;
y: number;
constructor(x: number, y: number);
constructor(xy: string);
constructor(x: string | number, y: number = 0) {
// 初始化逻辑
}
}
2. 父类构造函数的 super
调用
在继承中,子类的构造函数中需要调用 super()
才能访问 this
:
class Base {
k = 4;
}
class Derived extends Base {
constructor() {
// 错误: 必须先调用 'super()'
console.log(this.k);
super();
}
}
五、方法 (Methods)
类方法用于定义对象的行为,可以与函数一样添加类型注解。
class Point {
x = 10;
y = 10;
scale(n: number): void {
this.x *= n;
this.y *= n;
}
}
方法中必须使用 this
访问类的属性和其他方法。
六、访问器 (Getters / Setters)
访问器是获取和设置字段的另一种方式,可以在访问或修改字段时添加逻辑。
class C {
_length = 0;
get length() {
return this._length;
}
set length(value) {
this._length = value;
}
}
如果访问器中只有 get
,则该属性会被推断为只读属性。
不同类型的访问器
自 TypeScript 4.3 起,get
和 set
可以有不同的类型:
class Thing {
_size = 0;
get size(): number {
return this._size;
}
set size(value: string | number | boolean) {
const num = Number(value);
if (!Number.isFinite(num)) {
this._size = 0;
return;
}
this._size = num;
}
}
七、索引签名 (Index Signatures)
索引签名允许类以类似对象的方式存储键值对:
class MyClass {
[s: string]: boolean | ((s: string) => boolean);
check(s: string) {
return this[s] as boolean;
}
}
索引签名使得类可以存储具有不同类型的键值对,但通常更建议将这些数据存储在类外的对象中。
八、总结
TypeScript 的类提供了丰富的成员类型和控制机制,从而让代码更严谨、更具可读性。通过 readonly
、strictPropertyInitialization
、get
/set
等特性,开发者可以编写更加类型安全、结构清晰的面向对象代码。
推荐: