介绍一下 TS 中的泛型【热度: 118】

关键词:TS 泛型

TypeScript 的泛型是一种工具,它能够使代码更加灵活,能够适配多种类型而非单一的类型。泛型可以创建可重用的组件,这些组件可以支持多种类型的数据,而不失去类型检查时的安全性。

泛型的基本概念

在 TypeScript 中, 泛型使用一个类型变量,常见的类型变量有 T,U,V 等。通过类型变量,你可以创建一个可以适应任何类型的组件(比如函数、接口或类)。类型变量像是函数或类的一个特殊参数,但这个参数是类型而非具体的值。

泛型的使用场景

  1. 函数:你可以创建一个泛型函数,该函数可以接受任意类型的参数,同时保证输入参数和返回参数类型相同:
function identity<T>(arg: T): T {
  return arg;
}

这里 T 用作类型变量,可以捕获用户提供的类型(比如 number),然后这个类型将被用于函数的参数和返回类型。

  1. 接口:使用泛型定义接口可以创建可用于多种类型的接口。
interface GenericIdentityFn<T> {
  (arg: T): T;
}

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

let myIdentity: GenericIdentityFn<number> = identity;

这里 GenericIdentityFn 接口定义了一个属性,它是一个接收 T 类型参数并返回 T 类型的函数。

  1. typetype 关键字可以用来创建类型别名,它确实支持泛型。你可以为类型别名定义泛型参数,然后在使用该类型别名时指定具体的类型。

下面是使用泛型的类型别名的例子:

// 这里定义了一个带有泛型参数 T 的类型别名
type Container<T> = {
  value: T;
};

// 可以这样使用类型别名
let numberContainer: Container<number> = { value: 1 };
let stringContainer: Container<string> = { value: "Hello" };

// 使用类型别名定义函数类型
type ReturnFunction<T> = () => T;

// 这个函数返回一个数字
let myFunction: ReturnFunction<number> = () => 42;

// 使用带有两个参数的泛型
type KeyValue<K, V> = {
  key: K;
  value: V;
};

let keyValue: KeyValue<string, number> = { key: "testKey", value: 123 };

通过使用泛型,type 可以定义灵活的类型别名,使得别名能够用于各种不同的数据类型,同时保持类型的安全性。这使得你可以在类型别名中使用泛型来捕获传递给别名的类型信息。

  1. :泛型也可以用于类定义中,使得类可以灵活地与多种类型协作。
class GenericNumber<T> {
  zeroValue: T;
  add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
  return x + y;
};

这里,GenericNumber<T> 类具有一个类型为 T 的属性 zeroValue 和一个用两个 T 类型参数返回 T 类型的方法 add

泛型约束

有时你可能希望对泛型进行限制,只允许使用满足特定接口的类型。这称为泛型约束。

interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length); // Now we know it has a .length property, so no more error
  return arg;
}

在这里,我们约束了类型 T 必须遵从 Lengthwise 接口,确保传入的类型具有 length 属性。

泛型中使用类型参数

你还可以在泛型中使用类型参数本身。

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

let x = { a: 1, b: 2, c: 3 };

getProperty(x, "a"); // Okay
getProperty(x, "m"); // Error: Argument of type '"m"' isn't assignable to '"a" | "b" | "c"'

在这个示例中,getProperty 函数有两个参数:objkeyobj 是对象 TkeyT 中键的集合 keyof T 的成员。

通过泛型,TypeScript 允许你在保持类型安全的同时创建灵活,可适用于多种类型的组件。这样你就能够写出更加通用且易于复用的代码。