TypeScript 泛型

介绍

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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能...
    2o壹9阅读 3,788评论 0 48
  • 泛型 软件工程中,我们不仅要创建定义良好且一致的 API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,...
    罗彬727阅读 3,823评论 0 0
  • 泛型 泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种...
    一瓣山河阅读 2,910评论 0 1
  • 前言:泛型的英译generics [dʒɪˈnɛrɪks] 泛型;;范型;通用类型; 通用类型这四个字就是泛型的真...
    CondorHero阅读 1,765评论 0 1
  • 泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性泛...
    成熟稳重的李先生阅读 1,670评论 0 0

友情链接更多精彩内容