泛型接口允许我们在接口定义中使用类型参数,创建可复用的类型结构。泛型接口在定义通用的数据结构和 API 响应类型时特别有用。
在接口名称后添加 <T> 声明类型参数。
interface Container<T> {
value: T
}
const stringContainer: Container<string> = {
value: "hello"
}
const numberContainer: Container<number> = {
value: 123
}
console.log(stringContainer.value)
console.log(numberContainer.value)
Container<T> 接口有一个类型参数 T,使用时指定具体类型。
接口可以有多个类型参数。
interface Pair<K, V> {
key: K
value: V
}
const pair1: Pair<string, number> = {
key: "age",
value: 25
}
const pair2: Pair<number, boolean> = {
key: 1,
value: true
}
console.log(pair1)
console.log(pair2)
Pair<K, V> 接口有两个类型参数,分别表示键和值的类型。
接口可以定义泛型函数类型。
interface Transformer<T, R> {
(input: T): R
}
const stringToNumber: Transformer<string, number> = (input) => {
return input.length
}
const numberToString: Transformer<number, string> = (input) => {
return input.toString()
}
console.log(stringToNumber("hello"))
console.log(numberToString(123))
Transformer<T, R> 定义了一个函数类型,接受 T 类型参数,返回 R 类型值。
接口的方法可以使用接口的类型参数。
interface Repository<T> {
findById(id: number): T | undefined
findAll(): T[]
save(entity: T): void
delete(id: number): void
}
interface User {
id: number
name: string
email: string
}
class UserRepository implements Repository<User> {
private users: User[] = []
findById(id: number): User | undefined {
return this.users.find(u => u.id === id)
}
findAll(): User[] {
return [...this.users]
}
save(entity: User): void {
const index = this.users.findIndex(u => u.id === entity.id)
if (index >= 0) {
this.users[index] = entity
} else {
this.users.push(entity)
}
}
delete(id: number): void {
this.users = this.users.filter(u => u.id !== id)
}
}
const userRepo = new UserRepository()
userRepo.save({ id: 1, name: "张三", email: "zhangsan@example.com" })
console.log(userRepo.findById(1))
Repository<T> 定义了一个通用的数据仓库接口,UserRepository 实现了这个接口。
泛型接口可以继承其他接口。
interface BaseRepository<T> {
findById(id: number): T | undefined
findAll(): T[]
}
interface ExtendedRepository<T> extends BaseRepository<T> {
save(entity: T): void
delete(id: number): void
}
interface Product {
id: number
name: string
price: number
}
class ProductRepository implements ExtendedRepository<Product> {
private products: Product[] = []
findById(id: number): Product | undefined {
return this.products.find(p => p.id === id)
}
findAll(): Product[] {
return [...this.products]
}
save(entity: Product): void {
const index = this.products.findIndex(p => p.id === entity.id)
if (index >= 0) {
this.products[index] = entity
} else {
this.products.push(entity)
}
}
delete(id: number): void {
this.products = this.products.filter(p => p.id !== id)
}
}
ExtendedRepository 继承了 BaseRepository,添加了更多方法。
接口可以为类型参数提供默认值。
interface Response<T = any> {
code: number
message: string
data: T
}
const response1: Response = {
code: 200,
message: "success",
data: { name: "张三" }
}
const response2: Response<string> = {
code: 200,
message: "success",
data: "操作成功"
}
console.log(response1)
console.log(response2)
Response<T = any> 的默认类型是 any,使用时可以省略类型参数。
泛型接口可以与索引签名结合使用。
interface Dictionary<T> {
[key: string]: T
}
const scores: Dictionary<number> = {
math: 90,
english: 85,
chinese: 88
}
const translations: Dictionary<string> = {
hello: "你好",
world: "世界"
}
console.log(scores.math)
console.log(translations.hello)
Dictionary<T> 定义了一个键值对结构,值的类型由 T 决定。
泛型接口在实际开发中常用于定义 API 响应和配置类型。
interface ApiResponse<T> {
code: number
message: string
data: T
timestamp: number
}
interface PaginatedResponse<T> extends ApiResponse<T[]> {
total: number
page: number
pageSize: number
}
interface User {
id: number
name: string
}
async function fetchUsers(page: number, pageSize: number): Promise<PaginatedResponse<User>> {
return {
code: 200,
message: "success",
data: [
{ id: 1, name: "张三" },
{ id: 2, name: "李四" }
],
timestamp: Date.now(),
total: 100,
page,
pageSize
}
}
async function main() {
const response = await fetchUsers(1, 10)
console.log(`总数: ${response.total}`)
console.log(`用户: ${response.data.map(u => u.name).join(", ")}`)
}
main()
泛型接口让 API 响应类型可以复用,同时保持类型安全。
泛型接口是定义可复用类型结构的重要工具。通过类型参数,接口可以适应不同的数据类型。泛型接口可以继承、设置默认类型参数,并与索引签名结合使用。在实际开发中,泛型接口常用于定义通用的数据结构和 API 响应类型。