首页 > 编程笔记 > JavaScript笔记 阅读:6

TypeScript泛型接口的用法(附带实例)

泛型与接口类似,不同之处在于,泛型没有属性和方法声明。接口中的属性或方法可能存在不确定的类型,这时就可以为接口定义泛型。只需在接口的属性或方法声明中引用这个泛型,在定义接口的实现类时指定泛型的具体类型即可。

比如,现在我们需要定义一个接口来包含不确定类型的对象数组,以及对象的增、删、改、查的方法,这里我们只演示添加和根据 id 查找两种情况。

由于接口内部要管理的数据对象的类型是不确定的,因此我们可以为这个接口定义泛型 T,内部的属性 data 为要管理的数据对象的数组,指定它为 T 类型的数组。add() 方法中接收的参数为数据对象,它的类型为 T 类型。getById() 方法的返回值为查找到的一个数据对象,因此将返回值声明为 T 类型。

泛型接口的代码如下:
interface IbaseCRUD<T> {
  data: T[];
  add(t: T) => void;
  getById: (id: number) => T | undefined;
}

后面添加了不同的类型,比如用户类型 User:
class User {
  id?: number;  // id 主键自增
  name: string;  // 姓名
  age: number;   // 年龄

  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

我们在定义操作 User 对象的 CRUD 类时,需要实现前面定义的泛型接口,此时就需要指定泛型的具体类型为 User。这样就会约束我们定义的 User 数组类型的 data 属性、add() 方法和 getById() 方法,且 add() 方法接收的参数必须是 User 类型的,getById() 方法的返回值必须是 User 类型的。

实现代码如下:
// 定义操作User对象的CRUD类UserCRUD
class UserCRUD implements IbaseCRUD<User> {
  data: User[] = [];

  add(user: User): void {
    user = { ...user, id: Date.now() };
    this.data.push(user);
    console.log('保存user', user.id);
  }

  getById(id: number): User | undefined {
    return this.data.find((item) => item.id === id);
  }
}

// 测试使用
const userCRUD = new UserCRUD();
userCRUD.add(new User('tom', 12));
userCRUD.add(new User('tom2', 13));
console.log(userCRUD.data);
这样利用泛型就实现了对指定类型进行约束的效果。如果我们需要扩展定义其他类型的数据和对应的 CRUD 类,只需要实现此泛型接口,就可以起到完美的约束效果。

相关文章