TypeScript 泛型

2020-04-09  本文已影响0人  五月烧

介绍

     在软件工程中,我们不仅要创建一致的定义良好的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'.

【参考】https://www.tslang.cn/docs/handbook/generics.html

上一篇 下一篇

猜你喜欢

热点阅读