在 TypeScript 中,类(class
)不仅是一个运行时的值(即可以实例化对象的构造函数),同时也是一个类型声明。具体来说,类在 TypeScript 中既声明了值,也声明了类型,并且它的类型分为两种:
- 实例化对象类型:描述通过
new
操作符创建的实例的结构。 - 类构造函数类型:描述类本身的结构(包括构造函数和静态成员)。
1. 类声明值
(1) 作为值
- 在运行时,类是一个普通的 JavaScript 构造函数。
- 它可以通过
new
关键字实例化对象。
示例
class User {name: string;constructor(name: string) {this.name = name;}greet(): void {console.log(`Hello, ${this.name}`);}
}// 使用类作为值
const user = new User("Alice");
user.greet(); // 输出 "Hello, Alice"
在这里:
User
是一个构造函数,可以在运行时通过new
创建实例。
2. 类声明类型
(1) 实例化对象类型
- 类本身也可以作为一个类型,用来描述通过
new
操作符创建的实例的结构。 - 这种类型被称为实例化对象类型。
示例
class User {name: string;constructor(name: string) {this.name = name;}greet(): void {console.log(`Hello, ${this.name}`);}
}// 使用类作为类型
function printUser(user: User): void {console.log(user.name);
}const alice = new User("Alice");
printUser(alice); // 输出 "Alice"
在这里:
User
被用作类型,表示alice
的类型是User
类的实例。
(2) 类构造函数类型
- 类本身也有一个类型,称为类构造函数类型,它描述了类的静态成员和构造函数签名。
- 这种类型可以通过
typeof ClassName
获取。
示例
class User {static defaultName: string = "Guest";name: string;constructor(name: string) {this.name = name;}greet(): void {console.log(`Hello, ${this.name}`);}
}// 使用类构造函数类型
function createUser(ctor: typeof User, name: string): User {return new ctor(name);
}const bob = createUser(User, "Bob");
bob.greet(); // 输出 "Hello, Bob"console.log(User.defaultName); // 输出 "Guest"
在这里:
typeof User
表示User
类的构造函数类型。createUser
函数接受一个类构造函数ctor
和一个名称name
,并通过new ctor(name)
创建实例。
3. 实例化对象类型与类构造函数类型的区别
特性 | 实例化对象类型 | 类构造函数类型 |
---|---|---|
定义 | 描述通过 new 创建的实例的结构。 | 描述类本身的结构(包括静态成员)。 |
获取方式 | 直接使用类名(如 User )。 | 使用 typeof ClassName 。 |
用途 | 用于限制实例的结构。 | 用于限制类构造函数的结构。 |
示例 | const user: User = new User(); | const ctor: typeof User = User; |
4. 综合示例
以下是一个综合示例,展示了如何同时使用实例化对象类型和类构造函数类型。
示例代码
class User {static defaultName: string = "Guest";name: string;constructor(name: string) {this.name = name || User.defaultName;}greet(): void {console.log(`Hello, ${this.name}`);}
}// 使用实例化对象类型
function printUser(user: User): void {console.log(user.name);
}// 使用类构造函数类型
function createUser(ctor: typeof User, name?: string): User {return new ctor(name);
}// 测试
const alice = new User("Alice");
printUser(alice); // 输出 "Alice"const guest = createUser(User);
guest.greet(); // 输出 "Hello, Guest"
在这里:
User
作为实例化对象类型,用于限制printUser
函数的参数类型。typeof User
作为类构造函数类型,用于限制createUser
函数的第一个参数类型。
5. 高级用法:泛型与类类型
结合泛型和类类型,可以实现更灵活的设计。
示例:工厂函数
class Point {x: number;y: number;constructor(x: number, y: number) {this.x = x;this.y = y;}
}function createInstance<T>(ctor: new (...args: any[]) => T, ...args: any[]): T {return new ctor(...args);
}const point = createInstance(Point, 10, 20);
console.log(point.x, point.y); // 输出 10, 20
在这里:
createInstance
是一个通用的工厂函数,接受一个类构造函数和构造参数,返回类的实例。new (...args: any[]) => T
是类构造函数类型的泛型约束。
6. 总结
- 类声明值:
- 类是一个运行时的构造函数,可以通过
new
创建实例。
- 类是一个运行时的构造函数,可以通过
- 类声明类型:
- 实例化对象类型:描述类实例的结构。
- 类构造函数类型:描述类本身的结构(包括静态成员和构造函数签名)。
- 区别:
- 实例化对象类型关注实例的属性和方法。
- 类构造函数类型关注类的静态成员和构造函数。
- 应用场景:
- 实例化对象类型用于限制实例的类型。
- 类构造函数类型用于限制类的类型(如工厂函数)。