介绍
在软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性,泛型,可以用来提高代码的重用性。在代码中,我们不仅需要支持当前设计的数据类型,同时也要支持将来的数据类型,泛型,提供了这种方便。
泛型-初探
- 不使用泛型
function identity(arg: number): number { return arg; }
// 或者
function identity(arg: any): any { return arg; }
- 使用泛型定义
function identity<T>(arg: T): T { return ard; }
// 这样我们使用的时候就很方便:
let outputStr: string = identity<string>('myString'); // 这里 `T` 明确了是 `string`类型
let outputNum: number = identity<number>(123); // 这里 `T` 明确了是 `number`类型
- 方法中使用泛型的扩展
function loggingIdentiry<T>(arg: Array<T>): Array<T>{ return arg; }
泛型接口
interface Resource<T>{
limit: number;
offset: number;
size: number;
items: Array<T>;
}
interface GenericIdentityFn<T>{
(arg: T): T;
}
泛型类
class GenericNumber<U>{
zeroValue: U;
add: (x: U, y: U) => U;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; }
泛型约束 extends
有时候我们需要确定某一类型一定具有某个属性,可以通过extends
实现
interface Lengthwise {
length: number;
}
function loggingIndetity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 如果没有`extends Lengthwise`的话,这里使用length编译的时候就会报错
return arg;
}
// 因为使用了约束,所以arg已经不是任意类型了,而是需要包含`length`属性的任意类型
loggingIdentity(3); // Error,number doesn't have a .length property 就会报错了。
loggingIdentity({ length: 10, value: 3 }); // ✔ 这样就是争取的使用方式了
在泛型约束中使用类型参数
声明一个类型参数,且它被另一个类型参数所约束,如 想要属性名从对象里获取这个属性,并且确保这个实行存在于对象obj
上,因此需要在这两个类型之间使用约束
function getProperty(obj: T, key: K) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, 'a'); // okay
getProperty(x, 'm'); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.
在泛型里使用类类型
在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; // typechecks!
createInstance(Bee).keeper.hasMask; // typechecks!
createInstance(Bee).keeper.nametag; // error: Property 'nametag' does not exist on type 'BeeKeeper'.
网友评论