Type Script --泛型 学习

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

  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 property

loggingIdentity({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 typechecks
createInstance(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 属性,则类型检测通过。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,451评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,172评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,782评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,709评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,733评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,578评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,320评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,241评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,686评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,878评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,992评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,715评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,336评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,912评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,040评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,173评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,947评论 2 355

推荐阅读更多精彩内容

  • object 变量可指向任何类的实例,这让你能够创建可对任何数据类型进程处理的类。然而,这种方法存在几个严重的问题...
    CarlDonitz阅读 913评论 0 5
  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,209评论 9 118
  • 写在开头:本人打算开始写一个Kotlin系列的教程,一是使自己记忆和理解的更加深刻,二是可以分享给同样想学习Kot...
    胡奚冰阅读 1,433评论 1 3
  • 起因来自以下短信:Hello everyone, thank you for doing such wonderf...
    爱吃土豆的两只牛阅读 281评论 0 1
  • 越来越喜欢能做好小事的人。 越来越喜欢能信守承诺的人。 越来越喜欢胸中有沟壑的人。 一个兄弟来电,工作遇到麻烦,郁...
    大树的森林阅读 241评论 0 0