ts中的 泛型

泛型(Generics)是 TypeScript 中的一种强大工具,它允许你在定义函数、类或接口时,不预先指定具体的类型,而是在使用时再指定。这样可以提高代码的灵活性和复用性。

泛型函数

  1. 泛型的语法是 <> 里写类型参数,一般可以用 T 来表示
  2. 在函数中使用泛型,可以让函数适用于多种类型。
function identity<T>(arg: T): T {
    return arg;
}
  • 函数 identity 使用了泛型类型参数 T, 参数 arg 的类型为 T,返回值的类型也是 T,表示参数和返回值的类型可以是任何类型。
  • 泛型的语法是 <> 里写类型参数,一般可以用 T 来表示。T就是个占位符,在使用时可以把类型像参数一样传入
  1. 简单使用
// 创建泛型函数
function identity<T>(arg: T): T {
  return arg;
}

//  使用泛型函数。<string>表示传递类型是string
let output = identity<string>("myString");
console.log(output); // myString

// 使用类型推断,自动推断泛型类型
let output2 = identity("myString");
console.log(output2); // myString

一个函数定义多个泛型参数

  1. 使用尖括号 <> 来定义多个泛型参数,多个参数之间用逗号 , 分隔
function test<T, K>(a: T, b: K): K{
    return b;
}
test<number, string>(10, "hello");// hello

泛型接口

  • 在定义接口时, 为接口中的属性或方法定义泛型类型
  • 在使用接口时, 再指定具体的泛型类型
// 定义一个泛型接口
interface DataStorage<T> {
  data: T[]; // 存储数据的数组,类型为 T
  addItem: (item: T) => void; // 添加数据的方法
  getItems: () => T[]; // 获取所有数据的方法
}

// 实现这个泛型接口
class SimpleStorage<T> implements DataStorage<T> {
  data: T[] = []; // 初始化一个空数组来存储数据

  // 添加数据的方法
  addItem(item: T): void {
    this.data.push(item);
  }

  // 获取所有数据的方法
  getItems(): T[] {
    return this.data;
  }
}

// 使用这个泛型类存储不同类型的数据
const numberStorage = new SimpleStorage<number>(); // 存储数字
numberStorage.addItem(10);
numberStorage.addItem(20);
console.log(numberStorage.getItems()); // 输出: [10, 20]

const stringStorage = new SimpleStorage<string>(); // 存储字符串
stringStorage.addItem("Hello");
stringStorage.addItem("World");
console.log(stringStorage.getItems()); // 输出: ['Hello', 'World']

泛型类

  • 在定义类时, 为类中的属性或方法定义泛型类型
  • 在创建类的实例时, 再指定特定的泛型类型
// 定义一个泛型类 Box
class Box<T> {
  content: T;  // T 表示盒子里装的物品的类型

  // 构造函数接受一个参数,类型为 T
  constructor(value: T) {
    this.content = value;
  }

  // 获取盒子里内容的方法
  getContent(): T {
    return this.content;
  }
}

// 使用这个泛型类

// 创建一个装有数字的盒子
const numberBox = new Box<number>(42);
console.log(numberBox.getContent()); // 输出: 42

// 创建一个装有字符串的盒子
const stringBox = new Box<string>("Hello, TypeScript!");
console.log(stringBox.getContent()); // 输出: Hello, TypeScript!

// 创建一个装有数组的盒子
const arrayBox = new Box<number[]>([1, 2, 3]);
console.log(arrayBox.getContent()); // 输出: [1, 2, 3]

泛型约束

  1. 通过泛型约束,我们可以对泛型的类型进行限制,而不是允许它接受任意类型。
  2. extends 关键字: 用于对类型参数进行约束,使其必须是某个类型的子类型,或者必须实现某个接口。 这不仅限制了类型参数的种类,也确保了类型安全。
  3. 接口约束: 可以使用接口来定义类型参数的约束。
// 定义一个接口 Printable,指定实现该接口的类/对象必须包含一个名为 print 的方法
// 该方法不接受任何参数(即无参数),且不返回任何值(返回类型为 void)
interface Printable {
  // print 方法签名:无参数,返回 void
  print(): void;
}

// 定义一个泛型函数 printItem,带有类型参数 T
// T 被限制为必须扩展(实现)Printable 接口(通过 extends Printable 实现)
// 这意味着,只有当 T 是 Printable 的子类型(即实现了 Printable 接口)时,才能作为 printItem 的类型参数
function printItem<T extends Printable>( 
  // 函数参数 item 的类型被指定为 T,即 Printable 的子类型
  item: T
): void {
  // 在函数体内,安全地调用 item 的 print 方法,因为 TypeScript 确信 T 实现了 Printable
  item.print();
}
// 定义一个接口,包含我们希望对象必须有的属性
interface HasLength {
  length: number;
}

// 使用泛型约束,限制 T 必须是 extends HasLength 的类型
function logLength<T extends HasLength>(arg: T): void {
  console.log(arg.length); // 现在可以安全访问 length 属性
}

// 使用示例

// 字符串有 length 属性
logLength("Hello, TypeScript!"); // 输出: 19

// 数组也有 length 属性
logLength([1, 2, 3]); // 输出: 3

// 自定义对象,只要包含 length 属性也可以
logLength({ length: 7 }); // 输出: 7

// 下面这行代码会报错,因为数字没有 length 属性
// logLength(42); // 错误: 数字类型不满足 HasLength 约束
  1. 类约束: 可以约束类型参数必须是某个类的子类型。
// 定义一个 Animal 类
class Animal {
  // 属性:name,类型为 string
  name: string;

  // 构造函数,初始化 name 属性
  constructor(name: string) { 
    this.name = name; 
  }

  // 方法:move,接受一个可选参数 distanceInMeters(默认值为 0),打印移动信息
  move(distanceInMeters: number = 0) {
    console.log(`${this.name} moved ${distanceInMeters}m.`);
  }
}

// 定义一个泛型函数 createAnimalSound
// 类型参数 T 被约束为必须是 Animal 的子类型(通过 extends Animal 实现)
// 这意味着 T 可以是 Animal 本身,也可以是 Animal 的任何子类
function createAnimalSound<T extends Animal>( 
  // 函数参数 animal 的类型被指定为 T,即 Animal 的子类型
  animal: T
): string {
  // 函数体:返回一个字符串,包含 animal 的 name 和一句固定描述
  // 由于 T extends Animal,TypeScript 确信 animal 有一个名为 name 的属性
  return animal.name + " makes a sound";
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值