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

67 阅读3分钟

泛型函数示例:

泛型函数是一种能够在不同数据类型之间共享代码的方式,它们在TypeScript中提供了更大的灵活性和重用性。在上述示例中,我们定义了一个名为swap的泛型函数,用于交换传入的两个值。这个函数使用了类型参数T,这个类型参数充当了一个占位符,可以在函数体内代表任意类型。

这使得我们能够以一种通用的方式处理不同类型的值。例如,我们可以使用swap函数交换整数、字符串等,而不必为每种类型都编写一个单独的交换函数。这种泛型函数的设计方式不仅提高了代码的可读性,还节省了代码维护的工作量。

// 定义一个泛型函数,用于交换两个值的位置
function swap<T>(a: T, b: T): [T, T] {
    return [b, a];
}

const swapped = swap(10, 20); // 返回 [20, 10]
const swappedStrings = swap("hello", "world"); // 返回 ["world", "hello"]

泛型类示例:

泛型类是用于创建可以适用于多种数据类型的类的工具。在示例中,我们定义了一个名为Stack的泛型类,代表了一个简单的栈数据结构。这个栈可以存储任意类型的元素,因为在类的定义中我们使用了类型参数T

通过使用泛型类,我们可以创建适用于不同类型的栈实例,而不必为每种类型都编写一个独立的栈类。这种模式非常有用,因为它减少了代码冗余,并使得代码更具可维护性。

// 定义一个泛型类,表示一个简单的栈数据结构
class Stack<T> {
    private items: T[] = [];

    push(item: T) {
        this.items.push(item);
    }

    pop(): T | undefined {
        return this.items.pop();
    }
}

const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
console.log(numberStack.pop()); // 输出 2

const stringStack = new Stack<string>();
stringStack.push("a");
stringStack.push("b");
console.log(stringStack.pop()); // 输出 "b"

泛型接口示例:

泛型接口允许我们定义适用于不同类型的接口结构。在示例中,我们定义了一个名为KeyValuePair的泛型接口,用于表示键值对。这个接口使用了两个类型参数KV,分别代表键和值的类型。

通过使用这个泛型接口,我们可以创建适用于不同键值类型的对象。例如,我们可以使用KeyValuePair<string, number>来表示一个字符串键和一个数字值的键值对。这种灵活的设计使得我们可以创建通用的数据结构,适用于多种类型的数据。

// 定义一个泛型接口,表示一个键值对
interface KeyValuePair<K, V> {
    key: K;
    value: V;
}

const entry: KeyValuePair<string, number> = { key: "age", value: 25 };

使用类型约束来增加灵活性和安全性:

在泛型代码中,有时候我们希望对泛型类型进行一些限制,以确保特定的属性或方法在代码中可用。这就是类型约束的作用。在示例中,我们定义了一个名为printLength的泛型函数,它接受一个参数,并使用类型约束确保传入的参数具有length属性。

这种类型约束使得代码更加灵活,因为我们可以安全地使用参数对象的length属性而不必担心运行时错误。这也提高了代码的安全性,因为在编译阶段就可以捕获到不符合约束的错误。

// 使用类型约束来确保传入的参数具有length属性
function printLength<T extends { length: number }>(input: T) {
    console.log(`Length: ${input.length}`);
}

printLength([1, 2, 3]); // 输出 Length: 3
printLength("hello");   // 输出 Length: 5
// printLength(42);      // 错误,数字没有length属性

总的来说,泛型和类型约束是TypeScript中强大的功能,它们使得我们能够编写更加通用、灵活和安全的代码。通过泛型,我们可以避免重复编写类似的功能,通过类型约束,我们可以在编译阶段捕获一些错误,从而提高代码的可维护性和可读性。