实践记录TypeScript 类、泛型的使用 | 豆包MarsCode AI刷题

44 阅读8分钟

TypeScript 类、泛型的使用实践记录

泛型的概念和优势

泛型是 TypeScript 的核心特性之一,它允许我们为函数、接口和类创建可以操作多种类型的代码。使用泛型,我们可以写出更具可重用性和灵活性的代码。泛型的本质是参数化类型,这意味着我们可以在调用函数或类时指定具体的类型。

泛型的使用方法

泛型函数

泛型函数可以接收不同类型的参数,并返回相同类型的结果。这使得函数更加通用和灵活。例如,我们可以创建一个泛型函数来交换两个参数的位置,而不需要为每种数据类型编写不同的函数。

typescript
代码解读
复制代码
function swap<T>(tuple: [T, T]): [T, T] {
  return [tuple[1], tuple[0]];
}

const tuple = swap([1, 2]); // number[]
const strTuple = swap(["hello", "world"]); // string[]

泛型接口

泛型接口允许我们定义可以处理多种类型的接口。这在定义可以存储不同类型数据的结构时非常有用。

泛型类

泛型类允许我们在类的实例化时指定其属性或方法的类型。这使得类可以被用于多种类型的数据,而不需要为每种类型创建一个单独的类。

类型约束

类型约束提供了一种方式来限制泛型可以是哪些类型。这可以通过 extends 关键字来实现,它允许我们定义一个泛型必须是某个类型或其子类型的实例。

typescript
代码解读
复制代码
function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

const result = getProperty({ foo: "bar" }, "foo"); // string

在这个例子中,K extends keyof T 表示 K 必须是 T 的键之一。这样,getProperty 函数就可以确保 key 参数是 obj 对象的有效键。

泛型和类型约束的实际应用

代码的灵活性和安全性

通过使用泛型和类型约束,我们可以创建出既灵活又安全的代码。例如,我们可以创建一个函数,它接受一个对象和一个键,并返回对象中对应键的值。如果键不存在于对象中,函数将返回 undefined。这种类型安全性确保了我们的代码在编译时就能发现潜在的错误。

减少代码重复

泛型允许我们编写出可以用于多种类型的代码,而不需要为每种类型编写重复的代码。这不仅减少了代码的重复,也使得代码库更加简洁和易于维护。

提高代码的可读性和可维护性

使用泛型和类型约束可以提高代码的可读性,因为它们提供了关于函数、接口和类如何使用的具体信息。同时,它们也使得代码更加易于维护,因为任何对泛型类型的更改都只会在一个地方进行,而不是在代码库的多个地方。

泛型在高级场景中的应用

条件类型

TypeScript 的条件类型允许我们基于一个表达式的值来创建一个新的类型。这在结合泛型使用时非常有用,因为它允许我们根据输入类型来精细控制输出类型。

typescript
代码解读
复制代码
type ElementType<T> = T extends any[] ? T[number] : T;

const array = [1, 2, 3] as const;
type ArrayType = ElementType<typeof array>; // number

在这个例子中,ElementType 泛型类型检查 T 是否是一个数组,如果是,它提取数组的元素类型;如果不是,它直接返回 T

泛型工具类型

TypeScript 提供了一些内置的泛型工具类型,如 Partial<T>Readonly<T>Pick<T, K> 等,它们可以与泛型结合使用来创建复杂的类型操作。

typescript
type PartialPoint = Partial<Point>; // { x?: number; y?: number; }
type ReadonlyPoint = Readonly<Point>; // { readonly x: number; readonly y: number; }
type XYPoint = Pick<Point, 'x' | 'y'>; // { x: number; y: number; }

泛型和高阶函数

高阶函数是那些接收函数作为参数或返回函数的函数。结合泛型,我们可以创建非常强大的高阶函数,它们可以操作多种类型的函数。

typescript
function curry<T, U, V>(func: (a: T, b: U) => V): (a: T) => (b: U) => V {
  return function (a: T) {
    return function (b: U): V {
      return func(a, b);
    };
  };
}

const add = curry<number, number, number>((x, y) => x + y);
const increment = add(1);
console.log(increment(2)); // 输出:3

在这个例子中,curry 函数接受一个泛型函数,并返回一个新的函数,这个新函数接受第一个参数,并返回一个接受第二个参数的函数。

类型推断和泛型

TypeScript 的类型推断系统在处理泛型时非常强大。它能够根据传入的参数自动推断出泛型的类型,这减少了需要显式指定类型的需要。

typescript
function loggingIdentity<T>(value: T): T {
  console.log(value);
  return value;
}

const result = loggingIdentity("Hello World"); // 推断出 T 为 string

在这个例子中,尽管没有显式指定 T 的类型,TypeScript 编译器能够根据传入的参数 "Hello World" 推断出 T 是 string 类型。

类型兼容性和泛型

在使用泛型时,理解类型兼容性非常重要。泛型不会改变函数或类的类型签名,它们只是提供了一种方式来复用类型信息。

typescript
function combine<T>(x: T, y: T): T {
  return x + y as T; // 这里的实现是错误的,只是为了演示类型兼容性
}

const combined = combine(1, 2); // 正确,因为 1 和 2 都是 number
const combinedStrings = combine("Hello", "World"); // 错误,因为 "+" 操作符不适用于 string

在这个例子中,尽管 combine 函数使用了泛型 T,但是它仍然需要确保 x 和 y 可以被相加。如果 T 是 string 类型,那么直接相加是合法的,但如果 T 是其他类型,可能就需要不同的处理方式。

结论

泛型是 TypeScript 中一个强大的特性,它允许开发者编写出更加灵活和安全的代码。通过泛型,我们可以创建出能够处理多种数据类型的函数、接口和类,同时保持代码的简洁性和可维护性。类型约束进一步增强了泛型的表达能力,允许我们对泛型参数施加限制,以确保代码的正确性和安全性。掌握泛型的高级用法,如条件类型和泛型工具类型,可以让我们更加深入地理解和利用 TypeScript 的类型系统。通过这些高级特性,我们可以构建出更加复杂和强大的类型操作,以满足现代软件开发的需求。

TypeScript 类、泛型的使用实践记录

泛型的概念和优势

泛型是 TypeScript 的核心特性之一,它允许我们为函数、接口和类创建可以操作多种类型的代码。使用泛型,我们可以写出更具可重用性和灵活性的代码。泛型的本质是参数化类型,这意味着我们可以在调用函数或类时指定具体的类型。

泛型的使用方法

泛型函数

泛型函数可以接收不同类型的参数,并返回相同类型的结果。这使得函数更加通用和灵活。例如,我们可以创建一个泛型函数来交换两个参数的位置,而不需要为每种数据类型编写不同的函数。 trTuple = swap(["hello", "world"]); // string[]

泛型接口

泛型接口允许我们定义可以处理多种类型的接口。这在定义可以存储不同类型数据的结构时非常有用。

泛型类

泛型类允许我们在类的实例化时指定其属性或方法的类型。这使得类可以被用于多种类型的数据,而不需要为每种类型创建一个单独的类。

类型约束

类型约束提供了一种方式来限制泛型可以是哪些类型。这可以通过 extends 关键字来实现,它允许我们定义一个泛型必须是某个类型或其子类型的实例。

在这个例子中,K extends keyof T 表示 K 必须是 T 的键之一。这样,getProperty 函数就可以确保 key 参数是 obj 对象的有效键。

泛型和类型约束的实际应用

代码的灵活性和安全性

通过使用泛型和类型约束,我们可以创建出既灵活又安全的代码。例如,我们可以创建一个函数,它接受一个对象和一个键,并返回对象中对应键的值。如果键不存在于对象中,函数将返回 undefined。这种类型安全性确保了我们的代码在编译时就能发现潜在的错误。

减少代码重复

泛型允许我们编写出可以用于多种类型的代码,而不需要为每种类型编写重复的代码。这不仅减少了代码的重复,也使得代码库更加简洁和易于维护。

提高代码的可读性和可维护性

使用泛型和类型约束可以提高代码的可读性,因为它们提供了关于函数、接口和类如何使用的具体信息。同时,它们也使得代码更加易于维护,因为任何对泛型类型的更改都只会在一个地方进行,而不是在代码库的多个地方。

泛型在高级场景中的应用

条件类型

TypeScript 的条件类型允许我们基于一个表达式的值来创建一个新的类型。这在结合泛型使用时非常有用,因为它允许我们根据输入类型来精细控制输出类型。