TypeScript 泛型

来源: 2024-06-03 21:10:35 播报

使用泛型的主要目的是为了处理不特定类型的数据,使得代码可以适用于多种数据类型而不失去类型检查。

1、泛型的优势包括:

1)代码重用: 可以编写与特定类型无关的通用代码,提高代码的复用性。

2)类型安全: 在编译时进行类型检查,避免在运行时出现类型错误。

3)抽象性: 允许编写更抽象和通用的代码,适应不同的数据类型和数据结构。

2、泛型标识符

T: 代表 "Type",是最常见的泛型类型参数名。

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

K, V: 用于表示键(Key)和值(Value)的泛型类型参数。

interface KeyValuePair<K, V> {
    key: K;
    value: V;
}

E: 用于表示数组元素的泛型类型参数。

function printArray<E>(arr: E[]): void {
    arr.forEach(item => console.log(item));
}

R: 用于表示函数返回值的泛型类型参数。

function getResult<R>(value: R): R {
    return value;
}

U, V: 通常用于表示第二、第三个泛型类型参数。

function combine<U, V>(first: U, second: V): string {
    return `${first} ${second}`;
}

3、泛型函数

使用泛型来创建一个可以处理不同类型的函数:

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

// 使用泛型函数
let result = identity<string>("Hello");
console.log(result); // 输出: Hello

let numberResult = identity<number>(42);
console.log(numberResult); // 输出: 42

4、泛型接口

可以使用泛型来定义接口,使接口的成员能够使用任意类型:

// 基本语法
interface Pair<T, U> {
    first: T;
    second: U;
}

// 使用泛型接口
let pair: Pair<string, number> = { first: "hello", second: 42 };
console.log(pair); // 输出: { first: 'hello', second: 42 }

5、泛型类

泛型也可以应用于类的实例变量和方法:

// 基本语法
class Box<T> {
    private value: T;

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

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

// 使用泛型类
let stringBox = new Box<string>("TypeScript");
console.log(stringBox.getValue()); // 输出: TypeScript

6、泛型约束

有时候你想限制泛型的类型范围,可以使用泛型约束:

// 基本语法
interface Lengthwise {
    length: number;
}

function logLength<T extends Lengthwise>(arg: T): void {
    console.log(arg.length);
}

// 正确的使用
logLength("hello"); // 输出: 5

// 错误的使用,因为数字没有 length 属性
logLength(42); // 错误

7、泛型与默认值

可以给泛型设置默认值,使得在不指定类型参数时能够使用默认类型:

// 基本语法
function defaultValue<T = string>(arg: T): T {
    return arg;
}

// 使用带默认值的泛型函数
let result1 = defaultValue("hello"); // 推断为 string 类型
let result2 = defaultValue(42);      // 推断为 number 类型