TypeScript 类全面解析:从基础到高级特性
前言
TypeScript 作为 JavaScript 的超集,对 ES2015 引入的类(class)概念提供了全面支持,并在此基础上增加了类型系统和更多面向对象特性。本文将深入探讨 TypeScript 中类的各种特性和用法,帮助开发者更好地理解和使用这一重要概念。
类的基本结构
最简单的类定义
class Point {}
这个空类虽然现在没什么用,但它展示了类定义的最基本形式。在 TypeScript 中,类可以包含字段、构造函数、方法等多种成员。
类字段
类字段定义了类的实例属性:
class Point {
x: number;
y: number;
}
字段可以有类型注解,也可以有初始化器。当使用初始化器时,TypeScript 会自动推断字段类型:
class Point {
x = 0; // 推断为 number 类型
y = 0;
}
严格属性初始化
TypeScript 提供了 strictPropertyInitialization
选项,用于控制是否需要在构造函数中初始化类字段:
class BadGreeter {
name: string; // 错误:属性 'name' 没有初始化
}
class GoodGreeter {
name: string;
constructor() {
this.name = "hello";
}
}
如果确实需要通过其他方式初始化字段,可以使用明确赋值断言操作符 !
:
class OKGreeter {
name!: string; // 告诉 TypeScript 我们知道这个字段会被初始化
}
构造函数
类的构造函数与普通函数类似,可以带有参数、默认值和重载:
class Point {
x: number;
y: number;
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
}
在继承体系中,派生类必须在访问 this
前调用 super()
:
class Base {
k = 4;
}
class Derived extends Base {
constructor() {
super(); // 必须先调用 super()
console.log(this.k);
}
}
访问控制修饰符
TypeScript 提供了三种访问控制修饰符来控制类成员的可见性:
public
public
是默认修饰符,表示成员在任何地方都可以访问:
class Greeter {
public greet() {
console.log("hi!");
}
}
protected
protected
成员只能在类及其子类中访问:
class Greeter {
protected getName() {
return "hi";
}
}
class SpecialGreeter extends Greeter {
public howdy() {
console.log(this.getName()); // 可以访问
}
}
private
private
成员只能在类内部访问,子类也无法访问:
class Base {
private x = 0;
}
class Derived extends Base {
showX() {
console.log(this.x); // 错误:无法访问私有成员
}
}
需要注意的是,TypeScript 的 private
和 protected
只在编译时进行类型检查,运行时仍然可以访问。如果需要真正的运行时私有性,可以使用 JavaScript 的私有字段语法 #
:
class Dog {
#barkAmount = 0; // 真正的私有字段
}
静态成员
静态成员属于类本身而不是实例:
class MyClass {
static x = 0;
static printX() {
console.log(MyClass.x);
}
}
静态成员也可以有访问修饰符:
class MyClass {
private static x = 0;
}
继承与接口实现
继承
使用 extends
关键字实现继承:
class Animal {
move() {
console.log("Moving!");
}
}
class Dog extends Animal {
woof(times: number) {
for (let i = 0; i < times; i++) {
console.log("woof!");
}
}
}
接口实现
使用 implements
关键字实现接口:
interface Pingable {
ping(): void;
}
class Sonar implements Pingable {
ping() {
console.log("ping!");
}
}
高级特性
索引签名
类可以定义索引签名,用于处理动态属性:
class MyClass {
[s: string]: boolean | ((s: string) => boolean);
check(s: string) {
return this[s] as boolean;
}
}
泛型类
类可以是泛型的,类似于泛型接口:
class Box<T> {
contents: T;
constructor(value: T) {
this.contents = value;
}
}
const stringBox = new Box("hello");
this 绑定问题与解决方案
JavaScript 的 this
绑定有时会带来意外行为:
class MyClass {
name = "MyClass";
getName() {
return this.name;
}
}
const obj = {
name: "obj",
getName: new MyClass().getName
};
console.log(obj.getName()); // 输出 "obj" 而不是 "MyClass"
解决方案之一是使用箭头函数:
class MyClass {
name = "MyClass";
getName = () => {
return this.name;
};
}
总结
TypeScript 的类系统在 JavaScript 类的基础上增加了类型安全和更多面向对象特性。通过合理使用访问控制修饰符、继承、接口实现等特性,可以构建出更加健壮和可维护的代码结构。理解这些特性的工作原理和适用场景,对于编写高质量的 TypeScript 代码至关重要。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考