ts泛型

2024-07-11 12:16:51 294
泛型是 TypeScript 中的一项强大特性,它允许你在编写函数、类或接口时,不预先指定具体的类型,而在使用时再指定类型。这使得代码更加灵活和可复用。

泛型函数

泛型函数是最常见的泛型用法。你可以使用泛型来定义一个函数,使其能够处理多种类型,而不局限于单一类型。

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

let output1 = identity<string>("myString"); // 使用类型参数
let output2 = identity<number>(42); // 使用类型参数

在上面的例子中,identity 函数有一个类型参数 T,它表示任意类型。调用函数时,我们可以指定类型参数,如 identity<string>,也可以让 TypeScript 自动推断类型参数。

泛型变量

你可以在函数内部使用泛型变量,这样可以保证函数处理的类型一致。

function loggingIdentity<T>(arg: T[]): T[] {
  console.log(arg.length); // 泛型数组有length属性
  return arg;
}

let array = loggingIdentity<number>([1, 2, 3]);

在这个例子中,泛型变量 T 被用作数组类型,这样函数既可以处理 number[],也可以处理 string[] 等其他类型的数组。

泛型接口

接口也可以使用泛型,使得接口中的属性类型可以灵活地变化。

interface GenericIdentityFn<T> {
  (arg: T): T;
}

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

let myIdentity: GenericIdentityFn<number> = identity;

在这个例子中,GenericIdentityFn 接口定义了一个泛型函数类型。myIdentity 函数实现了这个接口,并且类型参数 T 被指定为 number

泛型类

类也可以使用泛型,使得类中的属性和方法可以根据不同的类型参数变化。

class GenericNumber<T> {
  zeroValue: T;
  add: (x: T, y: T) => T;
}

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

在这个例子中,GenericNumber 类使用了泛型 T,并且在实例化时指定了类型参数 number

泛型约束

有时候我们希望泛型类型变量满足某些条件,可以通过泛型约束来实现。

interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length); // 现在 `length` 属性是必需的
  return arg;
}

loggingIdentity({ length: 10, value: "hello" });

在这个例子中,T 被约束为 Lengthwise 类型,这样 loggingIdentity 函数中的 arg 参数必须有 length 属性。

在泛型中使用类型参数

你可以在泛型中使用另一个类型参数。

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

let x = { a: 1, b: 2, c: 3 };
let value = getProperty(x, "a"); // 1

在这个例子中,getProperty 函数有两个类型参数 TKK 被约束为 T 的键,确保 key 参数是 obj 对象的有效键。

泛型工具类型

TypeScript 提供了一些内置的泛型工具类型,用于在类型层面进行操作。

type Partial<T> = {
  [P in keyof T]?: T[P];
};

type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

interface Person {
  name: string;
  age: number;
}

type PartialPerson = Partial<Person>;
type ReadonlyPerson = Readonly<Person>;

在这个例子中,PartialReadonly 是两个内置的泛型工具类型,用于将接口的所有属性变为可选和只读。