本篇将介绍在TypeScript如何使用泛型。

一、泛型方法

在TypeScript里,声明泛型方法有以下两种方式:

 function generics_func1<T>(arg: T): T {
return arg;
}
// 或者
let generics_func2: <T>(arg: T) => T = function (arg) {
return arg;
}

调用方式也有两种:

 generics_func1<string>('Hello world');
// 或者
generics_func2('Hello world');

第二种调用方式可以省略类型参数,因为编译器会根据传入参数来自动识别对应的类型。

在之前介绍的基本类型里,有一个any类型,表示不确定的类型。在具体使用时,可以代替任意类型,比如如下方法定义和实现:

 function any_func(arg: any): any {
return arg;
} any_func(1);
any_func('Hello world!');
any_func(['1', '2']);

看似与泛型方法类似,但是还是有区别的。比如如下例子:

 // 方法一:带有any参数的方法
function any_func(arg: any): any {
console.log(arg.length);
return arg;
} // 方法二:Array泛型方法
function array_func<T>(arg: Array<T>): Array<T> {
console.log(arg.length);
return arg;
}

在方法一的方法体里,打印了arg参数的length属性。因为any可以代替任意类型,所以该方法在传入参数不是数组或者带有length属性对象时,会抛出异常。而方法二定义了参数类型是Array的泛型类型,肯定会有length属性,所以不会抛出异常。

从上面这个例子可以看出,泛型类型相比较any类型来说,在某些情况下会带有类型本身的一些信息,而any类型则没有。

二、泛型类

以下是一个泛型类的定义和调用

 class Generics_Demo<T>{
value: T;
show(): T {
return this.value;
}
} let gene_demo1 = new Generics_Demo<number>();
gene_demo1.value = 1;
console.log(gene_demo1.show()); // 调用方法 gene_demo1.show = function () { return gene_demo1.value + 1; } // 赋值新方法,返回值类型必须是number
console.log(gene_demo1.show());

通过指定明确类型的泛型类的实例,对属性赋值时,必须满足实际类型的约束。

三、泛型类型

以下几个例子都是利用泛型类型定义变量或者方法参数的类型的示例

1. 泛型接口

 interface Generics_interface {
<T>(arg: T): T;
} function func_demo<T>(arg: T): T {
return arg;
} let func1: Generics_interface = func_demo;

上面的例子里,接口只有一个泛型方法成员。则用此接口类型定义的变量就是一个与成员类型一致的泛型方法。

将上面例子的泛型接口稍微改一下

 interface Generics_interface<T> {
(arg: T): T;
} function func_demo<T>(arg: T): T {
return arg;
} let func1: Generics_interface<number> = func_demo;
func1(123); // 正确类型的实际参数
func1('123'); // 错误类型的实际参数

通过在接口上声明泛型,声明变量时明确指定泛型的具体类型,则赋值的方法将自动带上具体的类型约束。

2. 泛型类型继承

 interface LengthInterface {
length: number;
} function func_demo<T extends LengthInterface>(arg: T): T {
console.log(arg.length);
return arg;
} func_demo({ a: 1, length: 2 }); // 含有length属性的对象
func_demo([1, 2]); // 数组类型

上面的例子里,泛型类型继承自一个拥有length属性成员的接口,泛型类型将自动加上length属性的约束。调用时只有符合条件的对象才能正确赋值。

 function copy<T extends U, U>(source: U, target: T): T {
for (let prop in source) {
target[prop] = source[prop];
} return target;
} copy({ a: 1, b: 2 }, { a: 2, b: 3, c: 4 }); // 正确的实际参数
copy({ a: 1, b: 2 }, { q: 2, c: 4 }); // 错误的实际参数

在上面的例子里,一个泛型类型继承自另外一个泛型类型。在方法调用时,就必须确保继承类型对应的参数对象属性完全包含被继承类型对应的参数对象。

TypeScript学习笔记(五) - 泛型的更多相关文章

  1. Typescript 学习笔记五:类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  2. Typescript 学习笔记七:泛型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  3. Typescript 学习笔记六:接口

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  4. Typescript 学习笔记四:回忆ES5 中的类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  5. Typescript 学习笔记二:数据类型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  6. Typescript 学习笔记三:函数

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  7. Typescript 学习笔记一:介绍、安装、编译

    前言 整理了一下 Typescript 的学习笔记,方便后期遗忘某个知识点的时候,快速回忆. 为了避免凌乱,用 gitbook 结合 marketdown 整理的. github地址是:ts-gitb ...

  8. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  9. (转)Qt Model/View 学习笔记 (五)——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  10. java之jvm学习笔记五(实践写自己的类装载器)

    java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...

随机推荐

  1. OAuth 白话简明教程 5.其他模式

    转自:http://www.cftea.com/c/2016/11/6706.asp OAuth 白话简明教程 1.简述 OAuth 白话简明教程 2.授权码模式(Authorization Code ...

  2. Redis在Linux下的安装与配置

    Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. Redis是 NoSQL技术阵营中的一员. 说到NoSQL, ...

  3. spark环境安装

    源码包下载: http://archive.apache.org/dist/spark/spark-2.1.1/v 集群环境: master 192.168.1.99 slave1 192.168.1 ...

  4. table--边框样式设置

    Table的一些设置(自适应以及溢出)   table的两个属性 单行溢出点点显示 表格的宽度设置 双栏自适应连续连续英文符换行 1.table重置的两个属性: ①border-collapse: c ...

  5. JavaScript 预编译(变量提升和函数提升的原理)

    本文部分内容转自https://www.cnblogs.com/CBDoctor/p/3745246.html 1.变量提升 console.log(global); // undefined var ...

  6. LINUX实践--程序破解

    实验思想 本次实验的主要思想有两个,第一个是修改跳转指令,把它变成无条件跳转使得无论输入什么用户名都跳转到失败的那个选项中去,第二个思想是修改比对的内容,即不判断条件,从而成功 实验步骤 1.首先从老 ...

  7. 【转】为什么我的DIV块前总有空隙?

    在做网站项目时,博主爱吾所爱(爱生活=爱技术)很偶然地碰到一个奇怪的事情.我的DIV嵌套在另一个DIV里,总是出现这样一行空隙: Firebug查看内外两层DIV的margin, padding, l ...

  8. SqlBulkCopy 批量导入数据 转换表字段类型

    在使用SqlBulkCopy导入数据时,要有一个跟数据库里面同样的DataTable 要赋值表名 要求每个列跟数据库中列同名,并且列的类型要赋值跟数据库中列的类型对应的NET类型 要求数据库中为Nul ...

  9. (转载)Ubuntu 16.04+1080Ti机器学习基本环境配置

    转载自:https://blog.csdn.net/mahonesun/article/details/80808930 一.设置网络 机器有两张网卡,将当前正在使用的"有线连接1" ...

  10. 使用CAS实现无锁的SkipList

    无锁 并发环境下最常用的同步手段是互斥锁和读写锁,例如pthread_mutex和pthread_readwrite_lock,常用的范式为: void ConcurrencyOperation() ...