泛型基础概念
泛型是什么
泛型是编程语言中一种强大的特性,允许在定义函数、接口或类时不预先指定具体类型,而是在使用时再指定。TypeScript中的泛型提供了代码复用和类型安全之间的平衡。通过泛型,可以创建可重用的组件,这些组件能够支持多种类型而不牺牲类型检查。
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("hello");
let output2 = identity<number>(42);
泛型变量
在泛型函数内部,类型变量T代表任意类型。编译器要求必须正确使用这些泛型变量。当使用泛型创建类似数组这样的结构时,TypeScript知道数组方法的存在。
function loggingIdentity<T>(arg: T[]): T[] {
console.log(arg.length);
return arg;
}
function loggingIdentity2<T>(arg: Array<T>): Array<T> {
console.log(arg.length);
return arg;
}
泛型类型
泛型函数的类型与非泛型函数的类型没什么不同,只是有一个类型参数在最前面。可以使用不同的泛型参数名,只要数量和使用方式对应即可。
let myIdentity: <T>(arg: T) => T = identity;
let myIdentity2: <U>(arg: U) => U = identity;
interface GenericIdentityFn {
<T>(arg: T): T;
}
let myIdentity3: GenericIdentityFn = identity;
泛型类
泛型类看上去与泛型接口差不多,泛型类使用<>括起泛型类型,跟在类名后面。类有两部分:静态部分和实例部分,泛型类指的是实例部分的类型。
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; };
let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "";
stringNumeric.add = function(x, y) { return x + y; };
泛型约束
有时候需要限制泛型的类型范围,这时可以使用extends关键字来实现泛型约束。通过定义一个接口来描述约束条件,然后让泛型类型扩展这个接口。
interface Lengthwise {
length: number;
}
function loggingIdentity3<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
loggingIdentity3(3); // 错误,数字没有.length属性
loggingIdentity3({length: 10, value: 3}); // 正确
在泛型约束中使用类型参数
一个类型参数可以被另一个类型参数所约束。比如现在想要用属性名从对象里获取这个属性,并且需要确保这个属性存在于对象上。
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a"); // 正确
getProperty(x, "m"); // 错误:m不在x的key中
泛型中使用类类型
在TypeScript使用泛型创建工厂函数时,需要引用构造函数的类类型。通过原型属性推断并约束构造函数与类实例的关系。
class BeeKeeper {
hasMask: boolean;
}
class ZooKeeper {
nametag: string;
}
class Animal {
numLegs: number;
}
class Bee extends Animal {
keeper: BeeKeeper;
}
class Lion extends Animal {
keeper: ZooKeeper;
}
function createInstance<A extends Animal>(c: new () => A): A {
return new c();
}
createInstance(Lion).keeper.nametag;
createInstance(Bee).keeper.hasMask;
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn