TypeScript 作为 JavaScript 的超集,它在保留了 JavaScript 的灵活性的同时,通过引入静态类型系统增强了代码的可靠性和开发体验,提升了代码质量,使代码运行更加稳定。泛型是 TypeScript 中一个非常重要的特性,它允许我们在保持类型安全的同时编写可重用的代码组件。以下是一些关于 TypeScript 中泛型的使用方法和场景的实践记录,以及如何使用类型约束来增加代码的灵活性和安全性。
泛型的基本使用
1. 泛型函数
泛型函数可以处理不同类型的数据,而无需为每种类型重写函数。
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("Hello World");
let output2 = identity("Hello World"); // 类型推论
2. 泛型接口
泛型接口可以定义一个带有泛型的对象类型。
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
3. 泛型类
泛型类可以创建一个可以在多个类型上工作的组件。
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
泛型的使用场景
1. 数组和其他集合
泛型可以用来创建可重用的数组类型。
function loggingIdentity<T>(arg: T[]): T[] {
console.log(arg.length); // Array has a .length, so no more error
return arg;
}
2. 函数工厂
泛型可以用来创建返回不同类型函数的工厂函数。
function createLogger<T>(moduleName: string): (message: T) => void {
return function(message: T) {
console.log(`${moduleName}: ${message}`);
}
}
const logNumber: (message: number) => void = createLogger("NumberLogger");
const logString: (message: string) => void = createLogger("StringLogger");
类型约束
类型约束可以让我们指定泛型可以是哪些类型,从而增加代码的灵活性和安全性。
1. 使用 extends 约束泛型
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
2. 在泛型中使用类类型
可以使用泛型来约束类类型,从而创建可以在多个类上工作的组件。
function createInstance<A extends new (...args: any[]) => any>(ctor: A): InstanceType<A> {
return new ctor();
}
class BeeKeeper {
hasMask: boolean = true;
}
class ZooKeeper {
nametag: string = 'Mikle';
}
class Animal {
numLegs: number = 4;
}
class Bee extends Animal {
keeper: BeeKeeper = new BeeKeeper();
}
class Lion extends Animal {
keeper: ZooKeeper = new ZooKeeper();
}
function createInstance<A extends Animal>(ctor: new () => A): A {
return new ctor();
}
createInstance(Lion).keeper.nametag; // typechecks!
createInstance(Bee).keeper.hasMask; // typechecks!
通过上述的实践记录,我们可以看到泛型在 TypeScript 中的强大功能,它不仅能够提高代码的复用性,还能在编译时期提供类型检查,从而提高代码的安全性和可维护性。类型约束的使用则进一步增强了泛型的能力,允许我们定义更加精确的 API。