笔记五·TypeScript| 青训营

57 阅读3分钟

TypeScript泛型的使用实践记录

TypeScript中的泛型(Generics)是一种在编写函数、类或接口时,可以将类型作为参数传递的机制,从而增加代码的灵活性和重用性。它允许我们在定义函数或类的时候不指定具体的类型,而是在实际使用时再传入具体的类型参数。以下是一些关于如何使用TypeScript中的泛型的实践记录:

1. 泛型函数

泛型函数:通过在函数声明中使用泛型,可以让函数适用于不同类型的参数,同时保持类型的安全性。常见的场景包括:

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

let result = identity("Hello, TypeScript");
// result 的类型为 string,因为传入的参数类型为 string

2. 泛型类

泛型类:在类的定义中使用泛型,可以创建能够处理不同类型数据的通用类。常见的场景包括:

class Box<T> {
    private value: T;

    constructor(value: T) {
        this.value = value;
    }

    getValue(): T {
        return this.value;
    }
}

let boxOfString = new Box("TypeScript");
// boxOfString.getValue() 的类型为 string

let boxOfNumber = new Box(42);
// boxOfNumber.getValue() 的类型为 number

3. 泛型接口

泛型接口:可以使用泛型定义接口,使接口适用于不同的数据类型。

interface Pair<T, U> {
    first: T;
    second: U;
}

let pair: Pair<string, number> = { first: "one", second: 1 };

实例:

  1. 数组操作:在处理数组时,泛型可以帮助我们编写通用的函数,例如映射、筛选、查找等操作。

    typescriptCopy code
    function mapArray<T, U>(array: T[], mapper: (item: T) => U): U[] {
        return array.map(mapper);
    }
    
  2. Promise和异步操作:泛型可以用于处理异步操作返回的结果,确保类型的正确性。

    typescriptCopy code
    function asyncOperation<T>(data: T): Promise<T> {
        return new Promise(resolve => {
            // 异步操作
            resolve(data);
        });
    }
    
  3. 默认类型参数

可以为泛型设置默认的类型参数,这在一些场景下非常有用。

function getValueOrDefault<T = number>(value: T, defaultValue: T): T {
    return value !== undefined ? value : defaultValue;
}

let result = getValueOrDefault(undefined, 42);
// result 的类型为 number,默认使用了 number 类型的默认参数

4. 类型约束

可以使用类型约束来限制泛型的类型范围,使代码更安全。 以下是一些常见的类型约束使用场景:

function length<T extends { length: number }>(obj: T): number {
    return obj.length;
}

let strLength = length("TypeScript");
let arrLength = length([1, 2, 3]);
let objLength = length({ length: 5 });
  1. 限制属性存在:通过约束确保传入的泛型类型拥有某些属性。

    typescriptCopy code
    function getProperty<T, K extends keyof T>(obj: T, key: K) {
        return obj[key];
    }
    
  2. 限制类型范围:通过约束确保泛型类型属于特定的类型范围。

    typescriptCopy code
    function ensurePositiveNumber<T extends number>(value: T): number {
        return value > 0 ? value : 0;
    }
    
  3. 扩展已知类型:通过约束,可以使泛型继承已知类型的特性。

    typescriptCopy code
    function mergeObjects<T, U>(obj1: T, obj2: U): T & U {
        return { ...obj1, ...obj2 };
    }
    
  4. 限制函数参数类型:约束函数参数的类型以保证类型安全。

    typescriptCopy code
    function filterArray<T>(array: T[], predicate: (item: T) => boolean): T[] {
        return array.filter(predicate);
    }
    

通过泛型的类型约束,我们可以在编写通用代码时明确知道输入数据的类型,并在编译阶段捕获潜在的类型错误,从而增加代码的安全性和可维护性。无论是在函数、类、接口还是异步操作中,合理使用类型约束都能够让代码更加健壮和易于维护。

5. 使用泛型约束实现更具体的功能

泛型约束可以用于实现更具体的功能,例如在数组中查找某个元素。

function findElement<T>(arr: T[], predicate: (element: T) => boolean): T | undefined {
    for (let element of arr) {
        if (predicate(element)) {
            return element;
        }
    }
}

let numbers = [1, 2, 3, 4, 5];
let result = findElement(numbers, n => n % 2 === 0);
// result 的类型为 number | undefined,找到第一个偶数

泛型在TypeScript中的应用非常广泛,可以用于各种情况下增加代码的灵活性和重用性。无论是函数、类、接口还是类型别名,都可以结合泛型来实现更具有通用性的代码。同时,通过使用类型约束,还可以增加代码的安全性和可靠性,避免一些潜在的错误。