Type Script –泛型 学习

作者 : 开心源码 本文共3523个字,预计阅读时间需要9分钟 发布时间: 2022-05-12 共165人阅读

一. 场景
如何支持多种类型,并且还能保证数据完整性?
思考:
普通函数的样子?
定义参数->返回值。
二. 实现

  1. 泛型:
    在支持多种类型参数的同时,数据的完整性还能得到保证。
  2. 定义:类型变量
    指特殊的一种变量,只表示类型,不提供值。类型变量可以自己设置,只需在数量上和使用方式上能对应上即可以。
  3. 最基本的实现方法:
    通过类型变量替换掉参数的类型,<T>是函数签名,用来表示其是一个泛型函数。
function indentity <T>(arg: T){    return arg;}

我们有两种方法来使用此函数:
①公告返回值

let output = indentity<string> ("its me!");

② 无返回公告(类型推论)

let output = indentity ("its me!");

利用了类型推论 — 即编译器会根据传入的参数自动地帮助我们确定T的类型。

  1. 泛型变量
    当参数类型被标记为泛型变量后,那么当在方法体内使用这个参数时,必需把他当成任意类型。你不能在方法体内使用某些特定类型的方法,如使用arg.length(),由于你传递过来的可能是任何值,而数字就没有length方法。
  2. 任意类型的数组
    我们平常使用数组时,通常会公告此数组的类型,如:args : string[] 。此数组只能传递字符串类型。通过学习泛型,假如我们把这个数组改为泛型数组,那么我们即可以传递任意类型的值了。
    现在我们公告为 args : T[] 。
function loggingIdentity <T>(arg: T[]): T[] {    console.log(arg.length);  // Array has a .length, so no more error    return arg;}

我们既可以使用数组的方法,又可以传递任意的值了。

  1. 泛型类型
    思考:我们可以公告泛型数组以外的泛型类型吗?
    首先,我们看一下使用带有调用签名的对象字面量来定义泛型函数的写法:
function identity<T>(arg: T): T {    return arg;}let myIdentity: {<T>(arg: T): T} = identity;

函数的泛型类型表示为束缚函数的 参数类型返回值类型。<T>表示函数签名。
这种写法等同于:

function identity<T>(arg: T): T {    return arg;}let myIdentity: <T>(arg: T)=>T = identity;

对象字面量 可以单独拿出来,用来定义一个接口:

interface GenericIdentityFn {    <T>(arg: T): T;}

而后把这个接口作为函数的类型:

interface GenericIdentityFn {    <T>(arg: T): T;}function identity<T>(arg: T): T {    return arg;}let myIdentity : GenericIdentityFn = identity;

假如我们把函数签名从接口公告中拿出来,放到接口后面,就像这样:

interface GenericIdentityFn<T>{    (arg: T): T;}function identity<T>(arg: T): T {    return arg;}let myIdentity : GenericIdentityFn<number> = identity;

那么,当我们使用接口公告的时候,就需要同时传入<T>的类型,如上面例子里的number类型。可以根据需要,束缚使用时的类型了。
接下来,在接口的基础上,学习如何创立泛型类。

  1. 泛型类
    泛型类跟泛型接口差不多,同样是用<T>放在类名称后面,如
class GenericNumber<T>{  zeroValue:T ;  add:(x:T,y:T)=>T;}

add属性被公告为一个函数名称,并束缚了参数类型与返回值类型,但是此时并没有方法体。
当初始化这个类的时候,可以用任意类型,比方使用number类型:

let myGenericNumber=new GenericNumber<number>();myGenericNumber.zeroValue:T =0;myGenericNumber.add = (x,y)=>x+y;alert(myGenericNumber.add(myGenericNumber.zeroValue, 2));  //2

同样,也可以初始化的时候,传入string:

let myGenericNumber=new GenericNumber<number>();myGenericNumber.zeroValue:T ="1";myGenericNumber.add = (x,y)=>x+y;alert(myGenericNumber.add(myGenericNumber.zeroValue, "hello"));  //1hello

需要注意的是,泛型类里不能使用静态属性。起因是静态属性是类在公告时就进行初始化,跟类的实例无关。

  1. 泛型束缚
    我们还可以对<T>的内容进行束缚,比方T类型里面应该必需包含某一个属性,以方便我们程序的使用。
    还以接口为例子,这时候,我们需要在接口里面公告这个属性。
interface Lengthwise {    length: number;}

当使用泛型继承这个接口,那么就要求 实现T类型的类型里,必需包含length这个属性

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;}
loggingIdentity(3);  // Error, number doesn't have a .length propertyloggingIdentity({length: 10, value: 3});  //10 //right,{length: 10, value: 3}对象 包含 length属性。

另外的束缚使用:K类型被T类型束缚。本例里K类型必需被包含在T里。

function getProperty(obj: T, key: K) {    return obj[key];}

让我们最后看一下这个例子,你会怎样了解它呢?

class BeeKeeper {    hasMask: boolean;}class ZooKeeper {    nametag: string;}class Animal {    numLegs: number;}class Bee extends Animal {    keeper: BeeKeeper;}class Lion extends Animal {    keeper: ZooKeeper;}class Dog{   numLegs: number;}class Bird{  hasMask: boolean;  nametag: string;}function createInstance<A extends Animal>(c: new () => A): A {    return new c();}createInstance(Lion).keeper.nametag;  // typechecks!createInstance(Bee).keeper.hasMask;   // typechecks!createInstance(Bee).numLegs;    // typechecks!createInstance(Dog).numLegs;  // typechecks!createInstance(Bird).hasMask;   //error typecheckscreateInstance(Bird).nametag;  //error typechecks

解释:

由于泛型A继承了Animal的束缚,所以调用方法createInstance()时,参数对象必需包含Animal 类的属性 :numLegs;
参数(c: new () => A)会返回一个名为A的对象,但是没有值。方法体通过调用 new c() 这个构造方法生成一个类型为A的对象。
正如:createInstance(Bird).hasMask; //error typechecks
createInstance(Bird).nametag; //error typechecks
会报错:


Argument of type ‘typeof Bird’ is not assignable to parameter of type ‘new () => Animal’.
Type ‘Bird’ is not assignable to type ‘Animal’.
Property ‘numLegs’ is missing in type ‘Bird’.


而Dog由于包含了Animal的numLegs 属性,则类型检测通过。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Type Script –泛型 学习

发表回复