本篇将介绍在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 }); // 错误的实际参数

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

最新文章

  1. Oracle ORA-07445 evaopn2()+128错误问题
  2. Android常用组件之ListView
  3. 面向对象Part1对象的创建和Static!
  4. 【腾讯Bugly干货分享】iOS10 SiriKit QQ适配详解
  5. Linux文件查看/编辑方法介绍
  6. SNF开发平台WinForm之七-单据打印和使用说明-SNF快速开发平台3.3-Spring.Net.Framework
  7. MongoDB的学习--文档的插入、删除和更新
  8. 网站跨站点单点登录实现--cookie
  9. 生成整数自增ID(集群主键生成服务)
  10. MySql数据库的导入_命令工具
  11. 可选头 IMAGE_OPTIONAL_HEADER
  12. SQL模板和模板实例化
  13. 在 go/golang语言中使用 google Protocol Buffer
  14. php在客户端禁用cookie时让session不失效的解决方法
  15. python import xxx 与 from xxx import xx 模块引入的区别
  16. HNOI2019 游记
  17. python第一百零二天-----第十七周作业
  18. SpringBoot-热部署Devtools
  19. PHP echo()、print()、print_r()、var_dump()、var_export()的区别
  20. 第一次项目上Linux服务器(四:CentOS6下Mysql数据库的安装与配置(转))

热门文章

  1. VS2010/MFC编程入门之三十(常用控件:树形控件Tree Control 上)
  2. 34sqlite
  3. MapReduce: map读取文件的过程
  4. 883. Projection Area of 3D Shapes
  5. SecureCRT 会话空闲时超时退出处理
  6. Mac OS 终端下使用 Curl 命令下载文件
  7. TED #07# How to inspire every child to be a lifelong reader
  8. 六.__FILE__ , __LINE__ 与调试日志
  9. 如何解决tensorflow报:Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
  10. Ubuntu16.04 国内更新源