泛型类允许我们在类定义中使用类型参数,创建可以处理多种类型的类。泛型类在实现数据结构和工具类时特别有用。
在类名后添加 <T> 声明类型参数。
class Box<T> {
private value: T
constructor(value: T) {
this.value = value
}
getValue(): T {
return this.value
}
setValue(value: T): void {
this.value = value
}
}
const stringBox = new Box<string>("hello")
console.log(stringBox.getValue())
const numberBox = new Box(123)
console.log(numberBox.getValue())
Box<T> 类有一个类型参数 T,实例化时指定具体类型。TypeScript 可以根据构造函数参数推断类型。
类的属性和方法都可以使用类型参数。
class Stack<T> {
private items: T[] = []
push(item: T): void {
this.items.push(item)
}
pop(): T | undefined {
return this.items.pop()
}
peek(): T | undefined {
return this.items[this.items.length - 1]
}
size(): number {
return this.items.length
}
isEmpty(): boolean {
return this.items.length === 0
}
}
const numberStack = new Stack<number>()
numberStack.push(1)
numberStack.push(2)
numberStack.push(3)
console.log(numberStack.pop())
console.log(numberStack.peek())
console.log(numberStack.size())
Stack<T> 是一个通用的栈数据结构,可以存储任意类型的元素。
类可以有多个类型参数。
class KeyValuePair<K, V> {
constructor(
public key: K,
public value: V
) {}
toString(): string {
return `${String(this.key)}: ${String(this.value)}`
}
}
const pair1 = new KeyValuePair("name", "张三")
const pair2 = new KeyValuePair(1, true)
console.log(pair1.toString())
console.log(pair2.toString())
KeyValuePair<K, V> 类有两个类型参数,分别表示键和值的类型。
泛型类可以继承其他泛型类。
class Collection<T> {
protected items: T[] = []
add(item: T): void {
this.items.push(item)
}
getAll(): T[] {
return [...this.items]
}
size(): number {
return this.items.length
}
}
class UniqueCollection<T> extends Collection<T> {
add(item: T): void {
if (!this.items.includes(item)) {
super.add(item)
}
}
}
const uniqueNumbers = new UniqueCollection<number>()
uniqueNumbers.add(1)
uniqueNumbers.add(2)
uniqueNumbers.add(1)
console.log(uniqueNumbers.getAll())
console.log(uniqueNumbers.size())
UniqueCollection 继承了 Collection,重写了 add 方法确保元素唯一。
泛型类可以实现泛型接口。
interface Repository<T> {
findById(id: number): T | undefined
findAll(): T[]
save(entity: T): void
}
class MemoryRepository<T extends { id: number }> implements Repository<T> {
private items: T[] = []
findById(id: number): T | undefined {
return this.items.find(item => item.id === id)
}
findAll(): T[] {
return [...this.items]
}
save(entity: T): void {
const index = this.items.findIndex(item => item.id === entity.id)
if (index >= 0) {
this.items[index] = entity
} else {
this.items.push(entity)
}
}
}
interface User {
id: number
name: string
}
const userRepo = new MemoryRepository<User>()
userRepo.save({ id: 1, name: "张三" })
userRepo.save({ id: 2, name: "李四" })
console.log(userRepo.findById(1))
console.log(userRepo.findAll())
MemoryRepository 实现了 Repository 接口,T extends { id: number } 约束类型必须有 id 属性。
类的静态成员不能使用类的类型参数。
class Container<T> {
private static count: number = 0
constructor(private value: T) {
Container.count++
}
getValue(): T {
return this.value
}
static getCount(): number {
return Container.count
}
}
const c1 = new Container("hello")
const c2 = new Container(123)
const c3 = new Container(true)
console.log(Container.getCount())
静态成员属于类本身,不依赖于类型参数。每个实例共享静态成员。
泛型类可以约束类型参数的范围。
interface Comparable {
compareTo(other: this): number
}
class SortedList<T extends Comparable> {
private items: T[] = []
add(item: T): void {
this.items.push(item)
this.items.sort((a, b) => a.compareTo(b))
}
get(index: number): T | undefined {
return this.items[index]
}
getAll(): T[] {
return [...this.items]
}
}
class Person implements Comparable {
constructor(public name: string, public age: number) {}
compareTo(other: Person): number {
return this.age - other.age
}
}
const sortedList = new SortedList<Person>()
sortedList.add(new Person("张三", 25))
sortedList.add(new Person("李四", 20))
sortedList.add(new Person("王五", 30))
console.log(sortedList.getAll().map(p => p.name))
SortedList<T extends Comparable> 要求 T 必须实现 Comparable 接口,这样才能进行排序。
泛型类在实际开发中常用于实现工具类和数据结构。
class EventEmitter<Events extends Record<string, any>> {
private handlers: Partial<{ [K in keyof Events]: Array<(data: Events[K]) => void> }> = {}
on<K extends keyof Events>(event: K, handler: (data: Events[K]) => void): void {
if (!this.handlers[event]) {
this.handlers[event] = []
}
this.handlers[event]!.push(handler)
}
emit<K extends keyof Events>(event: K, data: Events[K]): void {
const handlers = this.handlers[event]
if (handlers) {
handlers.forEach(handler => handler(data))
}
}
off<K extends keyof Events>(event: K, handler: (data: Events[K]) => void): void {
const handlers = this.handlers[event]
if (handlers) {
const index = handlers.indexOf(handler)
if (index >= 0) {
handlers.splice(index, 1)
}
}
}
}
interface AppEvents {
login: { userId: number; name: string }
logout: { userId: number }
message: { from: string; content: string }
}
const emitter = new EventEmitter<AppEvents>()
emitter.on("login", (data) => {
console.log(`用户登录: ${data.name}`)
})
emitter.on("message", (data) => {
console.log(`收到消息: ${data.from} - ${data.content}`)
})
emitter.emit("login", { userId: 1, name: "张三" })
emitter.emit("message", { from: "李四", content: "你好" })
EventEmitter 是一个类型安全的事件发射器,使用泛型确保事件名称和数据类型的正确性。
泛型类是创建可复用类的重要工具。通过类型参数,类可以处理多种类型的数据。泛型类可以继承其他类、实现接口,并支持类型约束。静态成员不能使用类型参数。在实际开发中,泛型类常用于实现数据结构和工具类。