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

61 阅读3分钟

TypeScript是JavaScript的超集,它添加了静态类型、类、接口和其他许多功能,以提供更好的代码质量和更强大的开发体验。其中,泛型是TypeScript的一个重要特性,它允许我们编写更灵活、更通用的代码。

泛型的使用

在TypeScript中,泛型可以用于类、接口、函数和方法等。

泛型类

以下是一个泛型类的例子:

class Box<T> {
    content: T;
    constructor(content: T) {
        this.content = content;
    }
    get() {
        return this.content;
    }
}

在这个例子中,Box是一个泛型类,其类型参数为T。这个类有一个属性content,其类型为T,并且有一个构造函数,它接受一个类型为T的参数。此外,这个类还有一个get方法,它返回content的值。

你可以像下面这样使用这个类:

let a = new Box<string>("Hello");
let b = new Box<number>(123);
console.log(a.get()); // "Hello"
console.log(b.get()); // 123

泛型接口

以下是一个泛型接口的例子:

interface Generator<T> {
    (): T;
}

在这个例子中,Generator是一个泛型接口,它定义了一个返回类型为T的方法。你可以像下面这样使用这个接口:

function identity<T>(arg: T): T {
    return arg;
}
type Identity<T> = (arg: T) => T;
console.log(identity<string>("Hello")); // "Hello"
console.log((<Identity<number>>identity)(123)); // 123

类型约束

当你在使用泛型时,有时可能需要更具体的类型。这时,你可以使用类型约束。例如:

class Box<T extends string | number> {
    content: T;
    constructor(content: T) {
        this.content = content;
    }
    get() {
        return this.content;
    }
}

在这个例子中,Boxcontent的类型被限制为字符串或数字。这意味着你不能将其他类型的值传递给content。例如:

let a = new Box<string>("Hello"); // 正确
let b = new Box<number>(123); // 正确
let c = new Box<boolean>(true); // 错误,类型 'boolean' 不符合期望类型 'string | number'。

此外,你还可以在泛型中使用其他泛型。例如:

class Pair<T, U> {
    first: T;
    second: U;
    constructor(first: T, second: U) {
        this.first = first;
        this.second = second;
    }
}

在这个例子中,Pair是一个有两个类型参数的泛型类。你可以像下面这样使用这个类:

let a = new Pair<string, number>("Hello", 123); // 正确
let b = new Pair<number, string>(123, "Hello"); // 正确

除了上述的例子,泛型还可以在许多其他情况下使用,例如泛型函数、泛型方法、泛型索引等等。

泛型函数可以接受泛型参数,并返回泛型结果。例如,下面的函数可以接受一个数组和一个索引,并返回该索引处的元素。

tfunction getItem<T>(array: T[], index: number): T {
    return array[index];
}

泛型方法也可以接受泛型参数,并返回泛型结果。例如,下面的方法可以接受一个对象和一个键,并返回该键对应的值。

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

泛型索引可以用于定义可以使用字符串作为索引的接口。例如,下面的接口可以接受一个字符串作为索引,并返回对应的值。

interface Dictionary<T> {
    [index: string]: T;
}

除了上述的例子,泛型还有很多其他的应用场景。总的来说,泛型使得代码更加灵活和通用,可以用于处理许多不同类型的情况。同时,由于类型约束的存在,代码也更加安全。