TypeScript类系统详解:从基础到高级特性 1. TypeScript类基础概念TypeScript作为JavaScript的超集其类系统在ES6类的基础上进行了显著增强。类的本质是创建对象的模板它封装了数据属性和对数据的操作方法。在TypeScript中类不仅支持传统的面向对象特性还提供了类型注解、访问修饰符等额外功能。1.1 类的基本结构一个典型的TypeScript类包含以下部分class Person { // 属性声明可带类型注解 name: string; age: number; // 构造函数 constructor(name: string, age: number) { this.name name; this.age age; } // 方法 greet() { return Hello, my name is ${this.name}; } }与JavaScript类的主要区别在于显式的属性类型声明方法参数和返回值的类型注解编译时的类型检查1.2 类的实例化创建类实例时TypeScript会进行类型检查const person new Person(Alice, 30); console.log(person.greet()); // 正确用法 // 类型错误示例 const wrong new Person(123, 30); // 参数类型不匹配 wrong.greet 123; // 方法类型不匹配2. 类的高级特性2.1 访问修饰符TypeScript提供了三种访问控制修饰符修饰符类内子类实例public✓✓✓protected✓✓✗private✓✗✗典型应用class BankAccount { public readonly id: string; // 公开但只读 protected balance: number; // 仅限类和子类访问 private pin: string; // 仅限当前类访问 constructor(id: string, pin: string) { this.id id; this.pin pin; this.balance 0; } }2.2 抽象类抽象类用于定义类的基本结构而不完全实现abstract class Animal { abstract makeSound(): void; // 抽象方法 move(): void { console.log(Moving...); } } class Dog extends Animal { makeSound() { // 必须实现抽象方法 console.log(Bark!); } }抽象类的特点不能被直接实例化可以包含实现的方法子类必须实现所有抽象成员3. 类与接口3.1 实现接口TypeScript支持类实现一个或多个接口interface Loggable { log(): void; } class ConsoleLogger implements Loggable { log() { console.log(Logging...); } }3.2 接口继承类接口可以继承类的结构不包括实现class Point { x: number; y: number; } interface Point3D extends Point { z: number; } const point: Point3D { x: 1, y: 2, z: 3 };4. 高级类型与类4.1 类类型类本身可以作为类型使用class Greeter { greeting: string; constructor(message: string) { this.greeting message; } } let greeter: Greeter; // 使用类作为类型 greeter new Greeter(world);4.2 构造函数类型使用typeof获取类的构造函数类型class Widget { constructor(public name: string) {} } function createWidget(ctor: typeof Widget, name: string): Widget { return new ctor(name); }5. 装饰器与类类装饰器是TypeScript的实验性特性需要启用experimentalDecoratorsfunction sealed(constructor: Function) { Object.seal(constructor); Object.seal(constructor.prototype); } sealed class Greeter { greeting: string; constructor(message: string) { this.greeting message; } }常见装饰器类型类装饰器方法装饰器属性装饰器参数装饰器6. 类与模块6.1 类的导出与导入TypeScript支持ES模块语法// person.ts export class Person { constructor(public name: string) {} } // app.ts import { Person } from ./person; const p new Person(Alice);6.2 命名空间中的类对于较老的项目可以使用命名空间namespace Geometry { export class Point { constructor(public x: number, public y: number) {} } } const point new Geometry.Point(1, 2);7. 类的最佳实践7.1 设计原则单一职责原则每个类应该只有一个改变的理由开放封闭原则对扩展开放对修改封闭依赖倒置原则依赖抽象而非具体实现7.2 性能考量避免在类方法中创建大量临时对象谨慎使用继承层次建议不超过3层考虑使用对象池管理频繁创建的实例7.3 测试策略针对类的测试建议class Calculator { add(a: number, b: number): number { return a b; } } // 测试示例 describe(Calculator, () { it(should add numbers correctly, () { const calc new Calculator(); expect(calc.add(1, 2)).toEqual(3); }); });8. 常见问题与解决方案8.1 循环依赖问题当类A引用类B同时类B引用类A时// 解决方案1使用接口解耦 interface IUser { name: string; } class User implements IUser { name: string; } class Post { constructor(public author: IUser) {} } // 解决方案2延迟导入 class A { b: import(./b).B; }8.2 类型扩展问题扩展第三方库的类类型// 扩展Express的Request类型 declare global { namespace Express { interface Request { user?: User; } } }8.3 浏览器兼容性现代类语法在旧浏览器中的兼容方案配置target为es5或更低使用babel/plugin-transform-classes考虑使用类库如core-js的polyfill9. 实战案例实现一个状态机interface State { enter(): void; exit(): void; } class StateMachineT extends string { private states: RecordT, State; private current: T; constructor(initialState: T, states: RecordT, State) { this.current initialState; this.states states; this.states[initialState].enter(); } transitionTo(state: T) { this.states[this.current].exit(); this.current state; this.states[this.current].enter(); } } // 使用示例 class IdleState implements State { enter() { console.log(Enter idle); } exit() { console.log(Exit idle); } } class ActiveState implements State { enter() { console.log(Enter active); } exit() { console.log(Exit active); } } const machine new StateMachine(idle, { idle: new IdleState(), active: new ActiveState() }); machine.transitionTo(active);10. 未来演进TypeScript 5.0对类的改进方向更完善的装饰器标准支持类属性的运行时类型检查与ECMAScript新提案的更好集成对于baseUrl弃用的应对策略// tsconfig.json { compilerOptions: { paths: { /*: [src/*] // 替代baseUrl的方案 } } }