泛型基础
泛型允许我们在定义函数、类或接口时使用参数化类型,从而实现代码的通用性。例如:
function identity<T>(arg: T): T {return arg;
}let output = identity<string>("hello");
console.log(output); // 输出:hello
在上面的例子中,<T>
表示这是一个泛型函数,它接受一个类型为 T
的参数 arg
,并返回相同类型的值。我们在调用 identity
函数时指定了类型参数为 string
,从而确保返回值的类型与输入值相同。
泛型类型
除了函数之外,我们还可以使用泛型来定义接口和类。例如:
interface Pair<T, U> {first: T;second: U;
}let pair: Pair<number, string> = { first: 1, second: "two" };
console.log(pair); // 输出:{ first: 1, second: 'two' }
在上面的例子中,我们定义了一个名为 Pair
的泛型接口,它接受两个类型参数 T
和 U
,并具有 first
和 second
两个属性,分别对应这两种类型。
泛型约束
有时候,我们希望泛型具有某些特定的行为或属性。在这种情况下,我们可以使用泛型约束来限制泛型的类型。例如:
interface Lengthwise {length: number;
}function loggingIdentity<T extends Lengthwise>(arg: T): T {console.log(arg.length);return arg;
}loggingIdentity("hello"); // 输出:5
在上面的例子中,我们使用了泛型约束 extends Lengthwise
,表示 T
必须具有 length
属性。这样,我们就可以在函数中安全地访问 length
属性,而不必担心类型错误。
泛型在类中的应用
泛型不仅可以应用于函数和接口,还可以应用于类。例如:
class Box<T> {private value: T;constructor(value: T) {this.value = value;}getValue(): T {return this.value;}
}let box = new Box<number>(42);
console.log(box.getValue()); // 输出:42
在上面的例子中,我们定义了一个名为 Box
的泛型类,它接受一个类型参数 T
,并具有一个 getValue
方法,返回泛型类型 T
的值。
泛型与类型推断
TypeScript 具有强大的类型推断能力,可以根据上下文推断泛型的类型,从而使代码更加简洁和易读。例如:
function identity<T>(arg: T): T {return arg;
}let output = identity("hello");
console.log(output); // 输出:hello
在上面的例子中,尽管我们没有显式地指定类型参数,但 TypeScript 仍然能够推断出 output
的类型为 string
,因为参数 "hello"
的类型是已知的。
泛型的优势与应用场景
泛型可以使我们编写更加通用和灵活的代码,提高代码的重用性和可维护性。它在许多场景下都有着广泛的应用,例如容器类、函数库、异步编程等。通过合理地运用泛型,我们可以编写出更加健壮和可扩展的程序。