TypeScript学习笔记(六):泛型

认识泛型

TypeScript也实现了类型于C#和Java的泛型以实现类型的参数化,我们先看一个需求:

1 function identity(arg: any): any {
2     return arg;
3 }

我们希望方法identity可以传入任意类型,并且返回传入的类型,这样写可以达到效果但是不能确定返回的类型,使用泛型的写法如下:

1 function identity<T>(arg: T): T {
2     return arg;
3 }
4
5 var output = identity<string>("myString");  // type of output will be ‘string‘
6 var output = identity("myString");  // type of output will be ‘string‘

我们可以指定类型,也可以让编译器自动来识别类型。

泛型数组

我们也可以通过泛型来指定一个数组,写法如下:

1 function loggingIdentity<T>(arg: T[]): T[] {
2     console.log(arg.length);  // Array has a .length, so no more error
3     return arg;
4 }
5
6 function loggingIdentity<T>(arg: Array<T>): Array<T> {
7     console.log(arg.length);  // Array has a .length, so no more error
8     return arg;
9 }

泛型类型

我们可以指定一个带有泛型的函数:

1 function identity<T>(arg: T): T {
2     return arg;
3 }
4
5 var myIdentity: <U>(arg: U)=>U = identity;

还有另一种写法:

1 function identity<T>(arg: T): T {
2     return arg;
3 }
4
5 var myIdentity: {<T>(arg: T): T} = identity;

使用函数接口的写法如下:

1 interface GenericIdentityFn {
2     <T>(arg: T): T;
3 }
4
5 function identity<T>(arg: T): T {
6     return arg;
7 }
8
9 var myIdentity: GenericIdentityFn = identity;

同时泛型还可以作为类型的参数而不是方法的参数,写法如下:

1 interface GenericIdentityFn<T> {
2     (arg: T): T;
3 }
4
5 function identity<T>(arg: T): T {
6     return arg;
7 }
8
9 var myIdentity: GenericIdentityFn<number> = identity;

泛型类

泛型除了可以用在接口上以外,当然还可以用在类上:

 1 class GenericNumber<T> {
 2     zeroValue: T;
 3     add: (x: T, y: T) => T;
 4 }
 5
 6 var myGenericNumber = new GenericNumber<number>();
 7 myGenericNumber.zeroValue = 0;
 8 myGenericNumber.add = function(x, y) { return x + y; };
 9
10 var stringNumeric = new GenericNumber<string>();
11 stringNumeric.zeroValue = "";
12 stringNumeric.add = function(x, y) { return x + y; };
13 alert(stringNumeric.add(stringNumeric.zeroValue, "test"));

使用方法和C#与Java一致。

泛型约束

之前的泛型可以是任意的类型,我们还可以约束泛型的类型,我们先看一个会报错的例子:

1 function loggingIdentity<T>(arg: T): T {
2     console.log(arg.length);  // Error: T doesn‘t have .length
3     return arg;
4 }

报错原因是,类型T没有length属性,我们可以为类型T指定一个类型,如下:

1 interface Lengthwise {
2     length: number;
3 }
4
5 function loggingIdentity<T extends Lengthwise>(arg: T): T {
6     console.log(arg.length);  // Now we know it has a .length property, so no more error
7     return arg;
8 }

写法是通过extends来指定类型T的类型必须是实现了Lengthwise接口的类型。

调用如下:

1 loggingIdentity(3);  // Error, number doesn‘t have a .length property
2 loggingIdentity({length: 10, value: 3});  

泛型约束泛型

某些情况下,我们可能会有如下的需求:

1 function find<T, U extends Findable<T>>(n: T, s: U) {   // errors because type parameter used in constraint
2   // ...
3 }
4 find (giraffe, myAnimals);

这种写法会报错,可以使用下面正确的写法来达到效果:

1 function find<T>(n: T, s: Findable<T>) {
2   // ...
3 }
4 find(giraffe, myAnimals);

在泛型中使用类类型

有时我们希望可以指定泛型的构造函数和属性,写法如下:

1 function create<T>(c: {new(): T; }): T {
2     return new c();
3 }

再看另外一个例子:

 1 class BeeKeeper {
 2     hasMask: boolean;
 3 }
 4
 5 class ZooKeeper {
 6     nametag: string;
 7 }
 8
 9 class Animal {
10     numLegs: number;
11 }
12
13 class Bee extends Animal {
14     keeper: BeeKeeper;
15 }
16
17 class Lion extends Animal {
18     keeper: ZooKeeper;
19 }
20
21 function findKeeper<A extends Animal, K> (a: {new(): A;
22     prototype: {keeper: K}}): K {
23
24     return a.prototype.keeper;
25 }
26
27 findKeeper(Lion).nametag;  // typechecks!
时间: 2024-10-05 11:32:28

TypeScript学习笔记(六):泛型的相关文章

Java泛型学习笔记 - (六)泛型的继承

在学习继承的时候, 我们已经知道可以将一个子类的对象赋值给其父类的对象, 也就是父类引用指向子类对象, 如: 1 Object obj = new Integer(10); 这其实就是面向对象编程中的is-a关系. 既然上面的代码正确, 那么在泛型中, 也可以使用如下代码: 1 public class Box<T> { 2 private T obj; 3 4 public Box() {} 5 6 public T getObj() { 7 return obj; 8 } 9 10 pub

python之raw_input()(学习笔记六)

python之raw_input()(学习笔记六) 我们经常使用raw_input()读取用户的输入,如下例子所示: >>> name = raw_input('please input your name:'),截图如下: 下面简单说下,raw_input()与if搭配使用,脚本如下: #!/usr/bin/env python # -*- coding:utf-8 -*- birth = raw_input('birth:') if birth < 2000: print '0

swift学习笔记(六)析构过程和使用闭包对属性进行默认值赋值

一.通过闭包和函数实现属性的默认值 当某个存储属性的默认值需要定制时,可以通过闭包或全局函数来为其提供定制的默认值. 注:全局函数结构体和枚举使用关键字static标注    函数则使用class关键字标注 当对一个属性使用闭包函数进行赋值时,每当此属性所述的类型被创建实例时,对应的闭包或函数会被调用,而他们的返回值会被作为属性的默认值. ESC: Class SomeCLass{ let someProperty:SomeType={ //给someProperty赋一个默认值 //返回一个与

java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)

java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessController的checkPerssiom方法,访问控制器AccessController的栈检查机制又遍历整个 PerssiomCollection来判断具体拥有什么权限一旦发现栈中一个权限不允许的时候抛出异常否则简单的返回,这个过程实际上比我的描述要复杂 得多,这里我只是简单的一句带过,因为这

Java学习笔记_26_泛型概述

                                                               泛型概述 在Java中存入容器中的对象再取出时需要转换类型,因为对象加入容器会被转换成Object类型,而取出时要转换成实际类型.但向  下类型转换都 是存在潜在危险的,因此应该尽量避免它们.  Java的泛型: 所谓泛型就是在定义(类.方法.形参.成员变量等等)的时候,指 定它们为通用类型,也就是数据类型可以是任意类型. 泛型为提高大型程序的类型安全和维护带来了很大的潜

初探swift语言的学习笔记六(ARC-自动引用计数,内存管理)

Swift使用自动引用计数(ARC)来管理应用程序的内存使用.这表示内存管理已经是Swift的一部分,在大多数情况下,你并不需要考虑内存的管理.当实例并不再被需要时,ARC会自动释放这些实例所使用的内存. 另外需要注意的: 引用计数仅仅作用于类实例上.结构和枚举是值类型,而非引用类型,所以不能被引用存储和传递. swift的ARC工作过程 每当创建一个类的实例,ARC分配一个内存块来存储这个实例的信息,包含了类型信息和实例的属性值信息. 另外当实例不再被使用时,ARC会释放实例所占用的内存,这些

Linux System Programming 学习笔记(六) 进程调度

1. 进程调度 the process scheduler is the component of a kernel that selects which process to run next. 进程调度器需要使 处理器使用率最大化,并且提供 使多个进程并发执行的虚拟 Deciding which processes run, when, and for how long is the process scheduler's fundamental responsibility. 时间片:th

Lua学习笔记(六):函数-续

Lua中的函数是带有词法定界(lexical scoping)的第一类值(first-class values).第一类值指:在Lua中函数和其他值(数值.字符串)一样,函数可以被存放在变量中,也可以存放在表中,可以作为函数的参数,还可以作为函数的返回值.词法定界指:嵌套的函数可以访问他外部函数中的变量.这一特性给Lua提供了强大的编程能力. Lua中关于函数稍微难以理解的是函数也可以没有名字,匿名的.当我们提到函数名(比如print),实际上是说一个指向函数的变量,像持有其他类型的变量一样:

laravel3学习笔记(六)

原作者博客:ieqi.net ==================================================================================================== ORM Laravel3中MVC体系中Model里最重要的组成部分无疑是ORM了,ORM — object-relational mapper — 将数据操作面向对象化,使得整个web框架的核心风格统一,降低整体复杂度,为开发者提供便利. Laravel3中的ORM叫

IBatis.Net学习笔记六--再谈查询

在IBatis.Net学习笔记五--常用的查询方式 中我提到了一些IBatis.Net中的查询,特别是配置文件的写法. 后来通过大家的讨论,特别是Anders Cui 的提醒,又发现了其他的多表查询的方式.在上一篇文章中我提到了三种方式,都是各有利弊:第一种方式当数据关联很多的情况下,实体类会很复杂:第二种方式比较灵活,但是不太符合OO的思想(不过,可以适当使用):第三种方式最主要的问题就是性能不太理想,配置比较麻烦. 下面是第四种多表查询的方式,相对第二种多了一点配置,但是其他方面都很好(当然