TypeScript范型

栏目: typescript 发布时间:2024-11-01

在TypeScript中,范型(Generics)是一种强大的工具,它允许你在定义函数、接口或类时不具体指定类型,而是在使用时再指定。这样做的好处是增加了代码的复用性和类型安全性。范型通过参数化类型来工作,使得你可以编写与类型无关的代码,同时保持类型检查。

1. 范型函数

范型函数允许你在函数定义时不指定具体的类型,而是在调用函数时指定。

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

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

在这个例子中,identity 函数是一个范型函数,它接受一个类型为 T 的参数 arg 并返回相同类型的值。在调用 identity 函数时,我们通过 <string><number> 来指定类型参数。

你也可以让TypeScript编译器自动推断类型参数,而不需要显式指定:

let output3 = identity("anotherString"); // 自动推断为string
let output4 = identity(34); // 自动推断为number

2. 范型接口

范型接口允许你在接口中定义一个或多个类型参数,这些类型参数可以在接口的方法或属性中使用。

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

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

let myIdentity: GenericIdentityFn<number> = identityFn;
console.log(myIdentity(42)); // 输出: 42

在这个例子中,GenericIdentityFn 是一个范型接口,它描述了一个接受一个类型为 T 的参数并返回相同类型值的函数。然后,我们定义了一个符合 GenericIdentityFn<number> 类型的函数 identityFn,并将其赋值给 myIdentity 变量。

3. 范型类

范型类允许你在类定义中引入类型参数,这些类型参数可以在类的属性、方法或构造函数中使用。

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

  constructor(zeroValue: T, add: (x: T, y: T) => T) {
    this.zeroValue = zeroValue;
    this.add = add;
  }
}

let myGenericNumber = new GenericNumber<number>(0, function(x, y) { return x + y; });
console.log(myGenericNumber.add(1, 2)); // 输出: 3

在这个例子中,GenericNumber 是一个范型类,它有两个属性:zeroValueaddzeroValue 是类型为 T 的值,add 是一个接受两个类型为 T 的参数并返回类型为 T 的值的函数。然后,我们创建了一个 GenericNumber<number> 类型的实例,并为其提供了适当的 zeroValueadd 函数。

4. 泛型约束

有时,你可能希望对你使用的泛型进行约束,以确保它们至少具有某些属性或方法。这可以通过泛型约束来实现。

interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(arg.length); // 现在我们知道arg具有length属性,因为T被约束为Lengthwise
  return arg;
}

loggingIdentity({ length: 10, value: "hello!" }); // 输出: 10
loggingIdentity([1, 2, 3]); // 输出: 3

在这个例子中,我们定义了一个 Lengthwise 接口,它有一个 length 属性。然后,我们定义了一个 loggingIdentity 函数,它接受一个类型为 T 的参数,其中 T 被约束为 Lengthwise。这意味着 T 必须具有 length 属性。

5. 使用 keyoftypeof 在泛型约束中

keyoftypeof 是TypeScript中的高级类型操作,它们可以与泛型约束一起使用来创建更复杂的类型关系。

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

let person = { name: "Alice", age: 30 };
console.log(getProperty(person, "name")); // 输出: Alice
console.log(getProperty(person, "age"));  // 输出: 30

在这个例子中,getProperty 函数接受一个对象 obj 和一个字符串 key,其中 keyobj 的一个键。函数返回 obj[key] 的值,其类型为 T[K]。这里,K 被约束为 keyof T,意味着 K 必须是 T 的一个键。

范型是TypeScript中一个非常重要的特性,它允许你编写更加灵活和可重用的代码,同时保持类型安全性。通过定义范型函数、接口和类,以及使用泛型约束和高级类型操作,你可以创建出强大且易于维护的TypeScript应用程序。

本文地址:https://www.tides.cn/p_typescript-generics