TypeScript 类、泛型的使用实践记录|青训营

43 阅读3分钟

在TypeScript中,泛型(Generics)是一种强大的工具,用于创建可重用的、类型安全的代码。它允许我们在定义函数、类或接口时使用类型参数,以便在使用时指定具体的类型。

1. 函数泛型:

可以在函数定义中使用泛型来表示参数类型或返回值类型的灵活性。例如,我们可以编写一个通用的identity函数,它接受一个参数并返回相同的值,但可以适用于不同的类型:

function identity<T>(arg: T): T { 
   return arg; 
} 

let result = identity<string>("Hello");

2. 类泛型:

类也可以使用泛型来增加灵活性。例如,我们可以创建一个泛型的Box类,它可以存储不同类型的值:

class Box<T> { 
   private value: T; 
   
   constructor(value: T) {
      this.value = value; 
   } 
      
   getValue(): T { 
      return this.value; 
   } 
} 
   
let box1 = new Box<number>(10); 
let box2 = new Box<string>("Hello");

3. 接口泛型:

接口也可以使用泛型来定义灵活的类型。例如,我们可以创建一个泛型的List接口,表示一个具有不同类型元素的列表:

interface List<T> { 
   length: number; 
   getItem(index: number): T; 
   addItem(item: T): void; 
} 

class MyList<T> implements List<T> { 
   private items: T[] = []; 
   
   length: number = 0; 
   
   getItem(index: number): T { 
      return this.items[index]; 
   } 
   
   addItem(item: T): void {
      this.items.push(item); 
      this.length++; 
   } 
} 

let myList = new MyList<number>(); 
myList.addItem(10); 
myList.addItem(20);

泛型的使用可以增加代码的灵活性和安全性,具体体现在以下几个方面:

1. 类型安全性: 泛型可以在编译时提供类型检查,确保代码在使用时符合预期的类型。这可以避免在运行时出现类型错误。

2. 代码重用性: 泛型允许我们编写通用的代码,可以在不同的类型上进行操作,从而提高代码的重用性和可维护性。

3. 抽象数据类型: 泛型可以用于创建抽象的数据类型,使得代码更加通用和可扩展。通过泛型,我们可以定义适用于不同类型的数据结构和算法。

4. 接口和函数的灵活性: 使用泛型可以定义灵活的接口和函数,使其适用于不同类型的参数和返回值,从而增加代码的灵活性和可扩展性。

泛型约束即是对泛型的类型进行约束控制,如限制为object类型或指定接口类型当在函数里使用泛型参数的属性或者方法时,就需要对泛型进行约束。

1.接口约束

interface Lengthwise {
    length: number;
}
 
function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);     // 如果没有Lengthwise泛型约束,会报错Error: T doesn't have .length
    return arg;
}

2.object约束

function getKeys<T extends object>(data:T) :string[] {
    const keys:Array<string> = Object.keys(data)
    return keys
}

工具

TypeScript提供了一些内置的泛型工具类型,例如Partial、Readonly、Pick和Record等,它们可以帮助我们更方便地操作和处理复杂的类型。这些工具类型可以用来创建部分可选的类型、只读的类型、从现有类型中选取部分属性或将一个键值对列表转换为一个类型。通过使用这些工具类型,我们可以更加简洁和灵活地定义和操作复杂的类型。